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

Re: Regression: $~i is no expanded if $i contains dash



On Tue, 15 Nov 2016 14:26:37 +0100
Daniel Hahler <genml+zsh-workers@xxxxxxxxxx> wrote:
> Test case:
> 
> > hash -d t-t=/tmp; i="~t-t"; echo $~i; echo ~t-t
> ~t-t
> /tmp

I've realised what this means now.  Directory names can include a dash
since Unix user names can include a dash.

This is probably efficient enough, since the dupstring() only occurs
at the point we need to extract the directory name, which is once per
command line argument at most.

pws

diff --git a/Src/subst.c b/Src/subst.c
index 4471774..c7c5522 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -684,19 +684,19 @@ filesubstr(char **namptr, int assign)
 	    *namptr = dyncat(ds, ptr);
 	    return 1;
 	} else if ((ptr = itype_end(str+1, IUSER, 0)) != str+1) {   /* ~foo */
-	    char *hom, save;
+	    char *untok, *hom;
 
-	    save = *ptr;
-	    if (!isend(save))
+	    if (!isend(*ptr))
 		return 0;
-	    *ptr = 0;
-	    if (!(hom = getnameddir(++str))) {
+	    untok = dupstring(++str);
+	    untok[ptr-str] = 0;
+	    untokenize(untok);
+
+	    if (!(hom = getnameddir(untok))) {
 		if (isset(NOMATCH) && isset(EXECOPT))
-		    zerr("no such user or named directory: %s", str);
-		*ptr = save;
+		    zerr("no such user or named directory: %s", untok);
 		return 0;
 	    }
-	    *ptr = save;
 	    *namptr = dyncat(hom, ptr);
 	    return 1;
 	}
diff --git a/Src/utils.c b/Src/utils.c
index cceaf4c..92d8311 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -3959,7 +3959,7 @@ inittyptab(void)
 #endif
     /* typtab['.'] |= IIDENT; */ /* Allow '.' in variable names - broken */
     typtab['_'] = IIDENT | IUSER;
-    typtab['-'] = typtab['.'] = IUSER;
+    typtab['-'] = typtab['.'] = typtab[STOUC(Dash)] = IUSER;
     typtab[' '] |= IBLANK | INBLANK;
     typtab['\t'] |= IBLANK | INBLANK;
     typtab['\n'] |= INBLANK;
@@ -4157,42 +4157,50 @@ itype_end(const char *ptr, int itype, int once)
 	(itype != IIDENT || !isset(POSIXIDENTIFIERS))) {
 	mb_charinit();
 	while (*ptr) {
-	    wint_t wc;
-	    int len = mb_metacharlenconv(ptr, &wc);
-
-	    if (!len)
-		break;
-
-	    if (wc == WEOF) {
-		/* invalid, treat as single character */
-		int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
-		/* in this case non-ASCII characters can't match */
-		if (chr > 127 || !zistype(chr,itype))
-		    break;
-	    } else if (len == 1 && isascii(*ptr)) {
-		/* ASCII: can't be metafied, use standard test */
+	    int len;
+	    if (itok(*ptr)) {
+		/* Not untokenised yet --- can happen in raw command line */
+		len = 1;
 		if (!zistype(*ptr,itype))
 		    break;
 	    } else {
-		/*
-		 * Valid non-ASCII character.
-		 */
-		switch (itype) {
-		case IWORD:
-		    if (!iswalnum(wc) &&
-			!wmemchr(wordchars_wide.chars, wc,
-				 wordchars_wide.len))
-			return (char *)ptr;
-		    break;
+		wint_t wc;
+		len = mb_metacharlenconv(ptr, &wc);
 
-		case ISEP:
-		    if (!wmemchr(ifs_wide.chars, wc, ifs_wide.len))
-			return (char *)ptr;
+		if (!len)
 		    break;
 
-		default:
-		    if (!iswalnum(wc))
-			return (char *)ptr;
+		if (wc == WEOF) {
+		    /* invalid, treat as single character */
+		    int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
+		    /* in this case non-ASCII characters can't match */
+		    if (chr > 127 || !zistype(chr,itype))
+			break;
+		} else if (len == 1 && isascii(*ptr)) {
+		    /* ASCII: can't be metafied, use standard test */
+		    if (!zistype(*ptr,itype))
+			break;
+		} else {
+		    /*
+		     * Valid non-ASCII character.
+		     */
+		    switch (itype) {
+		    case IWORD:
+			if (!iswalnum(wc) &&
+			    !wmemchr(wordchars_wide.chars, wc,
+				     wordchars_wide.len))
+			    return (char *)ptr;
+			break;
+
+		    case ISEP:
+			if (!wmemchr(ifs_wide.chars, wc, ifs_wide.len))
+			    return (char *)ptr;
+			break;
+
+		    default:
+			if (!iswalnum(wc))
+			    return (char *)ptr;
+		    }
 		}
 	    }
 	    ptr += len;
diff --git a/Test/B09hash.ztst b/Test/B09hash.ztst
index 49f3048..7b5dfb4 100644
--- a/Test/B09hash.ztst
+++ b/Test/B09hash.ztst
@@ -69,3 +69,11 @@
 >one=/first/directory
 >two=/directory/the/second
 >three=/noch/ein/verzeichnis
+
+  hash -d t-t=/foo
+  i="~t-t"
+  print ~t-t/bar
+  print ${~i}/rab
+0:Dashes are untokenized in directory hash names
+>/foo/bar
+>/foo/rab



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