Mercurial > vim
diff src/vim9expr.c @ 28813:3626ca6a20ea v8.2.4930
patch 8.2.4930: interpolated string expression requires escaping
Commit: https://github.com/vim/vim/commit/0abc2871c105882ed1c1effb9a7757fad8a395bd
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue May 10 13:24:30 2022 +0100
patch 8.2.4930: interpolated string expression requires escaping
Problem: Interpolated string expression requires escaping.
Solution: Do not require escaping in the expression.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 10 May 2022 14:30:04 +0200 |
parents | 723c7d940cba |
children | bf013128ccf4 |
line wrap: on
line diff
--- a/src/vim9expr.c +++ b/src/vim9expr.c @@ -762,9 +762,9 @@ compile_call( argvars[0].v_type = VAR_UNKNOWN; if (*s == '"') - (void)eval_string(&s, &argvars[0], TRUE); + (void)eval_string(&s, &argvars[0], TRUE, FALSE); else if (*s == '\'') - (void)eval_lit_string(&s, &argvars[0], TRUE); + (void)eval_lit_string(&s, &argvars[0], TRUE, FALSE); s = skipwhite(s); if (*s == ')' && argvars[0].v_type == VAR_STRING && ((is_has && !dynamic_feature(argvars[0].vval.v_string)) @@ -1375,30 +1375,73 @@ compile_get_env(char_u **arg, cctx_T *cc } /* - * Compile "$"string"" or "$'string'". + * Compile $"string" or $'string'. */ static int compile_interp_string(char_u **arg, cctx_T *cctx) { typval_T tv; int ret; + int quote; int evaluate = cctx->ctx_skip != SKIP_YES; + int count = 0; + char_u *p; - // *arg is on the '$' character. - (*arg)++; + // *arg is on the '$' character, move it to the first string character. + ++*arg; + quote = **arg; + ++*arg; - if (**arg == '"') - ret = eval_string(arg, &tv, evaluate); - else - ret = eval_lit_string(arg, &tv, evaluate); + for (;;) + { + // Get the string up to the matching quote or to a single '{'. + // "arg" is advanced to either the quote or the '{'. + if (quote == '"') + ret = eval_string(arg, &tv, evaluate, TRUE); + else + ret = eval_lit_string(arg, &tv, evaluate, TRUE); + if (ret == FAIL) + break; + if (evaluate) + { + if ((tv.vval.v_string != NULL && *tv.vval.v_string != NUL) + || (**arg != '{' && count == 0)) + { + // generate non-empty string or empty string if it's the only + // one + if (generate_PUSHS(cctx, &tv.vval.v_string) == FAIL) + return FAIL; + tv.vval.v_string = NULL; // don't free it now + ++count; + } + clear_tv(&tv); + } + + if (**arg != '{') + { + // found terminating quote + ++*arg; + break; + } + + p = compile_one_expr_in_str(*arg, cctx); + if (p == NULL) + { + ret = FAIL; + break; + } + ++count; + *arg = p; + } if (ret == FAIL || !evaluate) return ret; - ret = compile_all_expr_in_str(tv.vval.v_string, TRUE, cctx); - clear_tv(&tv); + // Small optimization, if there's only a single piece skip the ISN_CONCAT. + if (count > 1) + return generate_CONCAT(cctx, count); - return ret; + return OK; } /* @@ -2161,14 +2204,14 @@ compile_expr8( /* * String constant: "string". */ - case '"': if (eval_string(arg, rettv, TRUE) == FAIL) + case '"': if (eval_string(arg, rettv, TRUE, FALSE) == FAIL) return FAIL; break; /* * Literal string constant: 'str''ing'. */ - case '\'': if (eval_lit_string(arg, rettv, TRUE) == FAIL) + case '\'': if (eval_lit_string(arg, rettv, TRUE, FALSE) == FAIL) return FAIL; break;