zsh-workers
 help / color / mirror / code / Atom feed
* Regression: $~i is no expanded if $i contains dash
@ 2016-11-15 13:26 ` Daniel Hahler
  2016-11-15 16:25   ` Peter Stephenson
  0 siblings, 1 reply; 2+ messages in thread
From: Daniel Hahler @ 2016-11-15 13:26 UTC (permalink / raw)
  To: zsh-workers


[-- Attachment #1.1: Type: text/plain, Size: 281 bytes --]

Test case:

> hash -d t-t=/tmp; i="~t-t"; echo $~i; echo ~t-t
~t-t
/tmp

It works fine in 5.2, and regressed in ad16356:

Author: Peter Stephenson
Date:   Tue Jan 19 17:24:12 2016 +0000

    37689: ! and ^ need to be tokenised in character sets


Cheers,
Daniel.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 163 bytes --]

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

* Re: Regression: $~i is no expanded if $i contains dash
  2016-11-15 13:26 ` Regression: $~i is no expanded if $i contains dash Daniel Hahler
@ 2016-11-15 16:25   ` Peter Stephenson
  0 siblings, 0 replies; 2+ messages in thread
From: Peter Stephenson @ 2016-11-15 16:25 UTC (permalink / raw)
  To: zsh-workers

On Tue, 15 Nov 2016 14:26:37 +0100
Daniel Hahler <genml+zsh-workers@thequod.de> 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


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

end of thread, other threads:[~2016-11-15 16:25 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20161115133740epcas3p3bc064157c11fa013d7e64f4ba6088bbd@epcas3p3.samsung.com>
2016-11-15 13:26 ` Regression: $~i is no expanded if $i contains dash Daniel Hahler
2016-11-15 16:25   ` 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).