Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

RC_EXPAND_PARAM final patch



Afther applying the included patch:

% a=(a b)
% x=(x y)
% echo ${x}1{a,b}2${x}
x y1a2x y1b2x y
% echo ${x}1${^a}2${x}
x y1a2x y1b2x y
% echo ${^x}1${a}2${x} 
x1a y1a b2x y
% echo ${^x}1${a}2${^x}
x1a y1a b2x b2y
% echo ${x}1{a,b}2${^x}
x y1a2x y1b2x y1a2y y1b2y
% echo ${x}1${^a}2${^x}
x y1a2x y1a2y y1b2x y1b2y
% echo ${^x}1{a,b}2${x} 
x1a2x x1b2x y1a2x y1b2x y
% echo ${^x}1${^a}2${x} 
x1a2x x1b2x y1a2x y1b2x y

This is consistent, predictable, and the implementation is simple.  The
patch applies to original zsh-3.0.4 and zsh-3.1.2.  If you have already
applied my previous two-line fix to subst.c, you will have to reverse
that patch before applying this.  It is enough to recompile utils.o and
subst.o.

There is still one point where the behaviour might be surprising: that's
when the (e) substitution flag is used:

% echo ${x}1${(e)^a}2${x}
x y1a2x y y1b2x y

With the (e) flag, the behaviour is the same as it was with
zsh-2.6-beta16 and earlier.  This is related to this behaviour:

% integer i=0
% foo=('$[i++]' '$[i++]')
% echo a${(e)^foo}b${(e)foo} 
a0b1 2 a3b4 5

Here a${(e)^foo}b${(e)foo} is substituted to two identical
a$[i++]b${(e)foo} arguments, and substitution for these arguments is
started from the beginning.  This is exatly the zsh-2.6-beta16 behaviour.
This can be (or maybe, should be) changed, but that would require much
more complicated changes.  Since most people probably do not even know
about the (e) flag, this would not affect too many scripts.  The (e) flag
can be used to get the value of a variable named by an other variable.
For example

% foo=ZSH_VERSION
% echo ${(e):-\$$foo}
3.1.2

Zoltan


*** Src/zsh.h	1997/06/30 04:33:16	3.1.3.1
--- Src/zsh.h	1997/05/04 05:18:36
***************
*** 69,74 ****
--- 69,80 ----
  # define STOUC(X)	((unsigned char)(X))
  #endif
  
+ /* Meta together with the character following Meta denotes the character *
+  * which is the exclusive or of 32 and the character following Meta.     *
+  * This is used to represent characters which otherwise has special      *
+  * meaning for zsh.  These are the characters for which the imeta() test *
+  * is true: the null character, and the characters from Meta to Marker.  */
+ 
  #define Meta		((char) 0x83)
  
  /* Note that the fourth character in DEFAULT_IFS is Meta *
***************
*** 103,108 ****
--- 109,117 ----
  #define Nularg		((char) 0x9b)
  
  #define INULL(x)	(((x) & 0xfc) == 0x98)
+ 
+ /* Marker used in paramsubst for rc_expand_param */
+ #define Marker		((char) 0x9c)
  
  /* chars that need to be quoted if meant literally */
  
*** Src/utils.c	1997/07/13 05:24:42	3.1.3.2
--- Src/utils.c	1997/08/02 04:36:54
***************
*** 2282,2288 ****
      typtab['\t'] |= IBLANK | INBLANK;
      typtab['\n'] |= INBLANK;
      typtab['\0'] |= IMETA;
!     typtab[STOUC(Meta)] |= IMETA;
      for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
  	typtab[t0] |= ITOK | IMETA;
      for (s = ifs ? ifs : DEFAULT_IFS; *s; s++) {
--- 2282,2289 ----
      typtab['\t'] |= IBLANK | INBLANK;
      typtab['\n'] |= INBLANK;
      typtab['\0'] |= IMETA;
!     typtab[STOUC(Meta)  ] |= IMETA;
!     typtab[STOUC(Marker)] |= IMETA;
      for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Nularg); t0++)
  	typtab[t0] |= ITOK | IMETA;
      for (s = ifs ? ifs : DEFAULT_IFS; *s; s++) {
*** Src/subst.c	1997/06/17 05:53:19	3.1.3.2
--- Src/subst.c	1997/08/02 06:05:47
***************
*** 1366,1377 ****
  	int i;
  	LinkNode on = n;
  
! 	if (!aval[0]) {
! 	    if (plan9) {
! 		uremnode(l, n);
! 		*str = aptr;
! 		return n;
! 	    }
  	    if (aptr > (char *) getdata(n) &&
  		aptr[-1] == Dnull && *s == Dnull)
  		*--aptr = '\0', s++;
--- 1366,1372 ----
  	int i;
  	LinkNode on = n;
  
! 	if (!aval[0] && !plan9) {
  	    if (aptr > (char *) getdata(n) &&
  		aptr[-1] == Dnull && *s == Dnull)
  		*--aptr = '\0', s++;
***************
*** 1398,1433 ****
  
  	if (plan9) {
  	    LinkList tl = newlinklist();
  
  	    addlinknode(tl, s);
  	    if (!eval && !stringsubst(tl, firstnode(tl), ssub))
  		return NULL;
  	    *str = aptr;
! 	    if (empty(tl)) {
! 		uremnode(l, n);
! 		return n;
! 	    }
! 	    i = 0;
! 	    while (aval[i]) {
! 		LinkNode tn;
! 
! 		x = aval[i++];
  		if (prenum || postnum)
  		    x = dopadding(x, prenum, postnum, preone, postone,
  				  premul, postmul);
  		if (eval && parsestr(x))
  		    return NULL;
  		xlen = strlen(x);
! 		for (tn = firstnode(tl); tn; incnode(tn)) {
! 		    strcatsub(&y, ostr, aptr, x, xlen,
! 			      (char *) getdata(tn), globsubst);
  		    if (qt && !*y && isarr != 2)
  			y = dupstring(nulstring);
! 		    if (i == 1)
! 			setdata(n, (void *) y);
  		    else
  			insertlinknode(l, n, (void *) y), incnode(n);
  		}
  	    }
  	} else {
  	    x = aval[0];
--- 1393,1439 ----
  
  	if (plan9) {
  	    LinkList tl = newlinklist();
+ 	    LinkNode tn;
  
+ 	    *--s = Marker;
  	    addlinknode(tl, s);
  	    if (!eval && !stringsubst(tl, firstnode(tl), ssub))
  		return NULL;
  	    *str = aptr;
! 	    tn = firstnode(tl);
! 	    while ((x = *aval++)) {
  		if (prenum || postnum)
  		    x = dopadding(x, prenum, postnum, preone, postone,
  				  premul, postmul);
  		if (eval && parsestr(x))
  		    return NULL;
  		xlen = strlen(x);
! 		for (tn = firstnode(tl);
! 		     tn && *(y = (char *) getdata(tn)) == Marker;
! 		     incnode(tn)) {
! 		    strcatsub(&y, ostr, aptr, x, xlen, y + 1, globsubst);
  		    if (qt && !*y && isarr != 2)
  			y = dupstring(nulstring);
! 		    if (plan9)
! 			setdata(n, (void *) y), plan9 = 0;
  		    else
  			insertlinknode(l, n, (void *) y), incnode(n);
  		}
+ 	    }
+ 	    for (; tn; incnode(tn)) {
+ 		y = (char *) getdata(tn);
+ 		if (*y == Marker)
+ 		    continue;
+ 		if (qt && !*y && isarr != 2)
+ 		    y = dupstring(nulstring);
+ 		if (plan9)
+ 		    setdata(n, (void *) y), plan9 = 0;
+ 		else
+ 		    insertlinknode(l, n, (void *) y), incnode(n);
+ 	    }
+ 	    if (plan9) {
+ 		uremnode(l, n);
+ 		return NULL;
  	    }
  	} else {
  	    x = aval[0];



Messages sorted by: Reverse Date, Date, Thread, Author