From 3059de44fa779b0a90fc33ef950814d6b0df84bc Mon Sep 17 00:00:00 2001 From: WATANABE Yuki Date: Sun, 25 Nov 2018 23:26:45 +0900 Subject: [PATCH] Don't tilde-expand modifier word in quoted parameter (#38728) --- NEWS | 3 +++ NEWS.ja | 3 +++ doc/expand.txt | 4 ++++ doc/ja/expand.txt | 5 ++++- expand.c | 13 +++++++------ tests/param-y.tst | 36 ++++++++++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 515d8815..f0e02d25 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,9 @@ Yash 2.48 + The prompt string now can be defined with the $YASH_PS... variables. = The default value of $PS1 has been changed. + = In quoted parameter expansion of the form "${foo+word}", + "${foo-word}", "${foo=word}", and "${foo?word}", the word is no + longer subject to tilde expansion. * The line number is now correctly counted in arithmetic expansions that contain newlines. * The variable name token in the for command and the word following diff --git a/NEWS.ja b/NEWS.ja index c941c30f..0f563289 100644 --- a/NEWS.ja +++ b/NEWS.ja @@ -12,6 +12,9 @@ Yash 2.48 + プロンプトを $YASH_PS... 変数で定義できるようにした = $PS1 の初期値を変更 + = 二重引用符内の "${foo+word}", "${foo-word}", "${foo=word}", + "${foo?word}" の形式のパラメータ展開では、加工指定内の単語は + チルダ展開しないようにした * 改行を含む数式展開の中で行番号が正しく数えられていなかった * for ループの変数名トークンあるいはヒアドキュメント演算子の直後の トークンが、値が空白で始まるエイリアス置換の結果である場合に、 diff --git a/doc/expand.txt b/doc/expand.txt index 25e7fb2f..aab4d0e6 100644 --- a/doc/expand.txt +++ b/doc/expand.txt @@ -359,6 +359,10 @@ the whole value. In all types of modifiers above, words are subjected to the four expansions when (and only when) they are used. +Exceptionally, when an expansion with a modifier of +-{{word}}+, +++{{word}}+, +={{word}}+, +?{{word}}+, +:-{{word}}+, +:+{{word}}+, ++:={{word}}+, or +:?{{word}}+ appears between link:syntax.html#quotes[double +quotes], the word is not subjected to tilde expansion. If {{parameter}} is an array variable or the link:params.html#sp-at[+@+] or link:params.html#sp-asterisk[+*+] special parameter, modifiers affect each diff --git a/doc/ja/expand.txt b/doc/ja/expand.txt index 389b54d8..573a9035 100644 --- a/doc/ja/expand.txt +++ b/doc/ja/expand.txt @@ -210,7 +210,10 @@ echo "${array[2,-2]}" +:/{{単語1}}/{{単語2}}+:: この加工指定は +/{{単語1}}/{{単語2}}+ と同様ですが、いま展開しようとしている値全体にマッチする場合しか対象としない点が異なります。 -いずれの形式においても、加工指定に含まれる単語は (それが使用されるときのみ) 四種展開されます。 +いずれの形式においても、加工指定に含まれる単語は (それが使用されるときのみ) 四種展開されます。ただし、加工指定 ++-{{word}}+, ++{{word}}+, +={{word}}+, +?{{word}}+, +:-{{word}}+, ++:+{{word}}+, +:={{word}}+, +:?{{word}}+ +を含むパラメータ展開が{zwsp}link:syntax.html#quotes[二重引用符]内で使用される場合は、単語にはチルダ展開が行われません。 展開しようとしている{{パラメータ名}}が配列変数または特殊パラメータ {zwsp}link:params.html#sp-at[+@+] または link:params.html#sp-asterisk[+*+] の場合、加工指定は配列の各要素または各位置パラメータに対してそれぞれ作用します。 diff --git a/expand.c b/expand.c index 3c535bf1..032b12b1 100644 --- a/expand.c +++ b/expand.c @@ -90,7 +90,7 @@ static wchar_t *trim_wstring(wchar_t *s, ssize_t startindex, ssize_t endindex) __attribute__((nonnull)); static void **trim_array(void **a, ssize_t startindex, ssize_t endindex) __attribute__((nonnull)); -static void print_subst_as_error(const paramexp_T *p) +static void print_subst_as_error(const paramexp_T *p, bool indq) __attribute__((nonnull)); static void match_each(void **restrict slist, const wchar_t *restrict pattern, paramexptype_T type) @@ -805,7 +805,8 @@ treat_array: if (unset) { subst: plfree(values, free); - return expand_four(p->pe_subst, TT_SINGLE, true, indq, true, e); + return expand_four(p->pe_subst, indq ? TT_NONE : TT_SINGLE, true, + indq, true, e); } break; case PT_ASSIGN: @@ -828,7 +829,7 @@ subst: return false; } subst = expand_single_and_unescape( - p->pe_subst, TT_SINGLE, true, false); + p->pe_subst, indq ? TT_NONE : TT_SINGLE, true, false); if (subst == NULL) return false; if (v.type != GV_ARRAY) { @@ -854,7 +855,7 @@ subst: case PT_ERROR: if (unset) { plfree(values, free); - print_subst_as_error(p); + print_subst_as_error(p, indq); return false; } break; @@ -1023,11 +1024,11 @@ void **trim_array(void **a, ssize_t startindex, ssize_t endindex) } /* Expands `p->pe_subst' and prints it as an error message. */ -void print_subst_as_error(const paramexp_T *p) +void print_subst_as_error(const paramexp_T *p, bool indq) { if (p->pe_subst != NULL) { wchar_t *subst = expand_single_and_unescape( - p->pe_subst, TT_SINGLE, true, false); + p->pe_subst, indq ? TT_NONE : TT_SINGLE, true, false); if (subst != NULL) { if (p->pe_type & PT_NEST) xerror(0, "%ls", subst); diff --git a/tests/param-y.tst b/tests/param-y.tst index 960e4eef..605c88c7 100644 --- a/tests/param-y.tst +++ b/tests/param-y.tst @@ -759,6 +759,42 @@ bcd abcde __OUT__ +test_oE 'no tilde expansion in quoted parameter expansion' +HOME=/home +unset x y z +bracket "${x-~}" ${x-"~"} "${x-"~"}" +bracket "${HOME+~}" ${HOME+"~"} "${HOME+"~"}" +bracket "${x=~}" ${y="~"} "${z="~"}" +__IN__ +[~][~][~] +[~][~][~] +[~][~][~] +__OUT__ + +test_Oe -e 2 'no tilde expansion in quoted parameter expansion (unset error 1)' +HOME=/home +unset x +eval 'bracket "${x?~}"' +__IN__ +eval: x: ~ +__ERR__ + +test_Oe -e 2 'no tilde expansion in quoted parameter expansion (unset error 2)' +HOME=/home +unset x +eval 'bracket ${x?"~"}' +__IN__ +eval: x: ~ +__ERR__ + +test_Oe -e 2 'no tilde expansion in quoted parameter expansion (unset error 3)' +HOME=/home +unset x +eval 'bracket "${x?"~"}"' +__IN__ +eval: x: ~ +__ERR__ + test_oE 'valid assignment to array element in expansion' a=('' '' '') bracket "${a[1]=x}" "${a[2]=y}" "${a[3]=z}" -- 2.19.1