zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: quote separators when using vared on array.
@ 2000-07-27 17:40 Peter Stephenson
  2000-07-27 21:59 ` Peter Stephenson
  0 siblings, 1 reply; 2+ messages in thread
From: Peter Stephenson @ 2000-07-27 17:40 UTC (permalink / raw)
  To: Zsh hackers list

I bet lots of people have run across this and thought `can't be bothered to
do anything, we'll wait for some schmuck to fix it'.

% print -l $path
/usr/local/bin
/bin
/c/WINNT/system32
/c/WINNT
/c/Program Files/Microsoft Office/Office
% vared path
<do nothing, hit return>
% print -l $path
/usr/local/bin
/bin
/c/WINNT/system32
/c/WINNT
/c/Program
Files/Microsoft
Office/Office

This is not right (and this time I'm not referring to the contents of the
final directory in $path).  This patch tries to do the minimum to fix
things, by quoting separators when reading an array, and unquoting them
when writing back to them.  I've stained the white radiance of utils.c with
a few comments, hope nobody minds.

Index: Doc/Zsh/mod_zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_zle.yo,v
retrieving revision 1.5
diff -u -r1.5 mod_zle.yo
--- Doc/Zsh/mod_zle.yo	2000/05/21 18:27:36	1.5
+++ Doc/Zsh/mod_zle.yo	2000/07/27 17:31:24
@@ -161,6 +161,12 @@
 If the type of an existing parameter does not match the type to be
 created, the parameter is unset and recreated.
 
+If an array or array slice is being edited, separator characters as defined
+in tt($IFS) will be shown quoted with a backslash.  Conversely, when the
+edited text is split into an array, a backslash quotes an immediately
+following separator character; no other special handling of backslashes, or
+any handling of quotes, is performed.
+
 Individual elements of existing array or associative array parameters
 may be edited by using subscript syntax on var(name).  New elements are
 created automatically, even without tt(-c).
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.13
diff -u -r1.13 exec.c
--- Src/exec.c	2000/07/19 20:43:51	1.13
+++ Src/exec.c	2000/07/27 17:31:25
@@ -2744,7 +2744,7 @@
 	}
 	addlinknode(ret, buf);
     } else {
-	char **words = spacesplit(buf, 0, 1);
+	char **words = spacesplit(buf, 0, 1, 0);
 
 	while (*words) {
 	    if (isset(GLOBSUBST))
Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.11
diff -u -r1.11 utils.c
--- Src/utils.c	2000/07/26 09:16:13	1.11
+++ Src/utils.c	2000/07/27 17:31:25
@@ -1831,7 +1831,7 @@
 
 /**/
 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 @@
 
     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 @@
 	    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 @@
 
 /**/
 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 '\<sep>' 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 @@
     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 @@
 	    break;
     }
     *s = t;
-    findsep(s, sep);
+    findsep(s, sep, 0);
     return t;
 }
 
@@ -1955,7 +1980,7 @@
     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 @@
 		if (mul <= 0)
 		    skipwsep(&s);
 	    }
-	    findsep(&s, NULL);
+	    findsep(&s, NULL, 0);
 	    t = s;
 	    if (mul <= 0)
 		skipwsep(&s);
@@ -2023,7 +2048,7 @@
     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 @@
 
     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);
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.7
diff -u -r1.7 zle_main.c
--- Src/Zle/zle_main.c	2000/07/19 21:10:18	1.7
+++ Src/Zle/zle_main.c	2000/07/27 17:31:25
@@ -823,7 +823,46 @@
 	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 @@
 	haso = 1;
     }
     /* edit the parameter value */
-    zpushnode(bufstack, ztrdup(s));
+    zpushnode(bufstack, s);
 
     varedarg = *args;
     ifl = isfirstln;
@@ -881,7 +920,11 @@
     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

-- 
Peter Stephenson <pws@csr.com>
Cambridge Silicon Radio, Unit 300, Science Park, Milton Road,
Cambridge, CB4 0XL, UK                          Tel: +44 (0)1223 392070


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: PATCH: quote separators when using vared on array.
  2000-07-27 17:40 PATCH: quote separators when using vared on array Peter Stephenson
@ 2000-07-27 21:59 ` Peter Stephenson
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Stephenson @ 2000-07-27 21:59 UTC (permalink / raw)
  To: Zsh hackers list

Peter Stephenson wrote:
> we'll wait for some schmuck to fix it

One day I'm going to learn to programme.  (This version actually tested
with nulls as separators.)

Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.12
diff -u -r1.12 utils.c
--- Src/utils.c	2000/07/27 17:48:48	1.12
+++ Src/utils.c	2000/07/27 21:57:43
@@ -1901,6 +1901,8 @@
 	    if (quote && *t == '\\' &&
 		isep(t[1] == Meta ? (t[2] ^ 32) : t[1])) {
 		chuck(t);
+		if (*t == Meta)
+		    t++;
 		continue;
 	    }
 	    if (*t == Meta) {

-- 
Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
Work: pws@CambridgeSiliconRadio.com
Web: http://www.pwstephenson.fsnet.co.uk


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2000-07-27 21:59 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-07-27 17:40 PATCH: quote separators when using vared on array Peter Stephenson
2000-07-27 21:59 ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).