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

Re: Quoting problem and crashes with ${(#)var}



On Feb 14, 10:16am, Peter Stephenson wrote:
} Subject: Re: Quoting problem and crashes with ${(#)var}
}
} > } (However, the ZLE function insert-unicode-char correctly
} > } shows it as control character, ^ followed by A with a grave accent.)
} > 
} > That's what I expected ${(V)x} to do, but instead it displays it as a
} > \u escape.
} >...
} > I'm asking for two things:
} > 
} > (1) when "character not in range" we don't treat it as a fatal error
} > and bail out of the whole surrounding loop; and

On further thought, it ought to be possible to test whether a character
is within range, so how about this:  Extend the (X) flag to cover (#)
as well as (Qqe).  Then ${(X#):-129} throws an error when LANG=C and
multibyte support is enabled, but ${(#):-129} does not.

Code (but not yet doc) patch below (ignore the diff in 23173).

} > (2) regardless of the locale, single-byte values should always be
} > convertible to something "viewable", either \u00xy or \M-c.
} 
} Passing the character through the appropriate version of nicechar()
} ought to help.

Unfortunately that doesn't seem to be enough:  the (V) flag is already
calling nicedupstring().  It looks like wcs_nicechar() only uses the
carat-character format for control characters less than 0x80?  ZLE
must be doing its own printable conversion somewhere else.


--- Src/subst.c	2007-02-14 07:59:29.000000000 -0800
+++ /tmp/subst.c	2007-02-14 07:59:29.000000000 -0800
@@ -1193,7 +1193,7 @@
 substevalchar(char *ptr)
 {
     zlong ires = mathevali(ptr);
-    int len;
+    int len = 0;
 
     if (errflag)
 	return NULL;
@@ -1204,7 +1204,8 @@
 	/* inefficient: should separate out \U handling from getkeystring */
 	sprintf(buf, "\\U%.8x", (unsigned int)ires);
 	ptr = getkeystring(buf, &len, GETKEYS_BINDKEY, NULL);
-    } else
+    }
+    if (len == 0)
 #endif
     {
 	ptr = zhalloc(2);
@@ -2658,6 +2659,10 @@
     if (errflag)
 	return NULL;
     if (evalchar) {
+	int one = noerrs, oef = errflag, haserr;
+
+	if (!quoteerr)
+	    noerrs = 1;
 	/*
 	 * Evaluate the value numerically and output the result as
 	 * a character.
@@ -2669,15 +2674,24 @@
 
 	    for (avptr = aval, av2ptr = aval2; *avptr; avptr++, av2ptr++)
 	    {
-		if (!(*av2ptr = substevalchar(*avptr)))
-		    return NULL;
+		/* When noerrs = 1, the only error is out-of-memory */
+		if (!(*av2ptr = substevalchar(*avptr))) {
+		    haserr = 1;
+		    break;
+		}
 	    }
 	    *av2ptr = NULL;
 	    aval = aval2;
 	} else {
+	    /* When noerrs = 1, the only error is out-of-memory */
 	    if (!(val = substevalchar(val)))
-		return NULL;
+		haserr = 1;
 	}
+	noerrs = one;
+	if (!quoteerr)
+	    errflag = oef;
+	if (haserr || errflag)
+	    return NULL;
     }
     /*
      * This handles taking a length with ${#foo} and variations.



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