From 921b39ac6b25dbfcc477fc7db4ed1c5c3ffb778c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 15 Nov 2016 18:01:32 +0000 Subject: 39949: Special case for "-" in directory names. It can be sh-tokenized to Dash to allow for appearing in ranges after substitution, so needs to be turned back to "-" in that case. --- ChangeLog | 4 ++++ Src/subst.c | 16 ++++++------- Src/utils.c | 70 +++++++++++++++++++++++++++++++------------------------ Test/B09hash.ztst | 8 +++++++ 4 files changed, 59 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 885777e37..0040c2367 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-11-15 Peter Stephenson + * 39949: Src/subst.c, Src/utils.c, Test/B09hash.ztst: "-" is + allowed in named directories, so needs a special case when + sh-tokenized for possible ranges. + * 39947: Test/D04parameter.ztst: Test out-of-rantge multiple array subscripts with and without (@). diff --git a/Src/subst.c b/Src/subst.c index 447177409..c7c552257 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 cceaf4c57..92d831172 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 49f304838..7b5dfb43e 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 -- cgit 1.4.1