comparison src/vim9compile.c @ 24498:bfa495227ac6 v8.2.2789

patch 8.2.2789: Vim9: using =expr in :substitute does not handle jumps Commit: https://github.com/vim/vim/commit/8238f08838c0b481d0b14a741bc03f2e45c211d3 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Apr 20 21:10:48 2021 +0200 patch 8.2.2789: Vim9: using \=expr in :substitute does not handle jumps Problem: Vim9: using \=expr in :substitute does not handle jumps. Solution: Start with instruction count zero. (closes https://github.com/vim/vim/issues/8128)
author Bram Moolenaar <Bram@vim.org>
date Tue, 20 Apr 2021 21:15:04 +0200
parents cca0a1b4e878
children 5baac0b4b41c
comparison
equal deleted inserted replaced
24497:b444a9f9b467 24498:bfa495227ac6
2174 isn_T *isn; 2174 isn_T *isn;
2175 2175
2176 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL) 2176 if ((isn = generate_instr_drop(cctx, ISN_EXECCONCAT, count)) == NULL)
2177 return FAIL; 2177 return FAIL;
2178 isn->isn_arg.number = count; 2178 isn->isn_arg.number = count;
2179 return OK;
2180 }
2181
2182 static int
2183 generate_substitute(char_u *cmd, int instr_start, cctx_T *cctx)
2184 {
2185 isn_T *isn;
2186 isn_T *instr;
2187 int instr_count = cctx->ctx_instr.ga_len - instr_start;
2188
2189 instr = ALLOC_MULT(isn_T, instr_count + 1);
2190 if (instr == NULL)
2191 return FAIL;
2192 // Move the generated instructions into the ISN_SUBSTITUTE instructions,
2193 // then truncate the list of instructions, so they are used only once.
2194 mch_memmove(instr, ((isn_T *)cctx->ctx_instr.ga_data) + instr_start,
2195 instr_count * sizeof(isn_T));
2196 instr[instr_count].isn_type = ISN_FINISH;
2197 cctx->ctx_instr.ga_len = instr_start;
2198
2199 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
2200 {
2201 vim_free(instr);
2202 return FAIL;
2203 }
2204 isn->isn_arg.subs.subs_cmd = vim_strsave(cmd);
2205 isn->isn_arg.subs.subs_instr = instr;
2206 return OK; 2179 return OK;
2207 } 2180 }
2208 2181
2209 /* 2182 /*
2210 * Generate ISN_RANGE. Consumes "range". Return OK/FAIL. 2183 * Generate ISN_RANGE. Consumes "range". Return OK/FAIL.
8520 } 8493 }
8521 8494
8522 return nextcmd; 8495 return nextcmd;
8523 } 8496 }
8524 8497
8498
8499 static void
8500 clear_instr_ga(garray_T *gap)
8501 {
8502 int idx;
8503
8504 for (idx = 0; idx < gap->ga_len; ++idx)
8505 delete_instr(((isn_T *)gap->ga_data) + idx);
8506 ga_clear(gap);
8507 }
8508
8525 /* 8509 /*
8526 * :s/pat/repl/ 8510 * :s/pat/repl/
8527 */ 8511 */
8528 static char_u * 8512 static char_u *
8529 compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx) 8513 compile_substitute(char_u *arg, exarg_T *eap, cctx_T *cctx)
8534 if (expr != NULL) 8518 if (expr != NULL)
8535 { 8519 {
8536 int delimiter = *cmd++; 8520 int delimiter = *cmd++;
8537 8521
8538 // There is a \=expr, find it in the substitute part. 8522 // There is a \=expr, find it in the substitute part.
8539 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), 8523 cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), NULL, NULL, NULL);
8540 NULL, NULL, NULL);
8541 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=') 8524 if (cmd[0] == delimiter && cmd[1] == '\\' && cmd[2] == '=')
8542 { 8525 {
8543 int instr_count = cctx->ctx_instr.ga_len; 8526 garray_T save_ga = cctx->ctx_instr;
8544 char_u *end; 8527 char_u *end;
8528 int trailing_error;
8529 int instr_count;
8530 isn_T *instr = NULL;
8531 isn_T *isn;
8545 8532
8546 cmd += 3; 8533 cmd += 3;
8547 end = skip_substitute(cmd, delimiter); 8534 end = skip_substitute(cmd, delimiter);
8548 8535
8536 // Temporarily reset the list of instructions so that the jumps
8537 // labels are correct.
8538 cctx->ctx_instr.ga_len = 0;
8539 cctx->ctx_instr.ga_maxlen = 0;
8540 cctx->ctx_instr.ga_data = NULL;
8549 compile_expr0(&cmd, cctx); 8541 compile_expr0(&cmd, cctx);
8550 if (end[-1] == NUL) 8542 if (end[-1] == NUL)
8551 end[-1] = delimiter; 8543 end[-1] = delimiter;
8552 cmd = skipwhite(cmd); 8544 cmd = skipwhite(cmd);
8553 if (*cmd != delimiter && *cmd != NUL) 8545 trailing_error = *cmd != delimiter && *cmd != NUL;
8554 { 8546
8555 semsg(_(e_trailing_arg), cmd); 8547 instr_count = cctx->ctx_instr.ga_len;
8548 instr = ALLOC_MULT(isn_T, instr_count + 1);
8549 if (trailing_error || instr == NULL)
8550 {
8551 if (trailing_error)
8552 semsg(_(e_trailing_arg), cmd);
8553 clear_instr_ga(&cctx->ctx_instr);
8554 cctx->ctx_instr = save_ga;
8555 vim_free(instr);
8556 return NULL; 8556 return NULL;
8557 } 8557 }
8558 8558
8559 if (generate_substitute(arg, instr_count, cctx) == FAIL) 8559 // Move the generated instructions into the ISN_SUBSTITUTE
8560 // instructions, then restore the list of instructions before
8561 // adding the ISN_SUBSTITUTE instruction.
8562 mch_memmove(instr, cctx->ctx_instr.ga_data,
8563 instr_count * sizeof(isn_T));
8564 instr[instr_count].isn_type = ISN_FINISH;
8565
8566 cctx->ctx_instr = save_ga;
8567 if ((isn = generate_instr(cctx, ISN_SUBSTITUTE)) == NULL)
8568 {
8569 int idx;
8570
8571 for (idx = 0; idx < instr_count; ++idx)
8572 delete_instr(instr + idx);
8573 vim_free(instr);
8560 return NULL; 8574 return NULL;
8575 }
8576 isn->isn_arg.subs.subs_cmd = vim_strsave(arg);
8577 isn->isn_arg.subs.subs_instr = instr;
8561 8578
8562 // skip over flags 8579 // skip over flags
8563 if (*end == '&') 8580 if (*end == '&')
8564 ++end; 8581 ++end;
8565 while (ASCII_ISALPHA(*end) || *end == '#') 8582 while (ASCII_ISALPHA(*end) || *end == '#')
9283 ret = OK; 9300 ret = OK;
9284 9301
9285 erret: 9302 erret:
9286 if (ufunc->uf_def_status == UF_COMPILING) 9303 if (ufunc->uf_def_status == UF_COMPILING)
9287 { 9304 {
9288 int idx;
9289 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) 9305 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
9290 + ufunc->uf_dfunc_idx; 9306 + ufunc->uf_dfunc_idx;
9291 9307
9292 for (idx = 0; idx < instr->ga_len; ++idx) 9308 clear_instr_ga(instr);
9293 delete_instr(((isn_T *)instr->ga_data) + idx);
9294 ga_clear(instr);
9295 VIM_CLEAR(dfunc->df_name); 9309 VIM_CLEAR(dfunc->df_name);
9296 9310
9297 // If using the last entry in the table and it was added above, we 9311 // If using the last entry in the table and it was added above, we
9298 // might as well remove it. 9312 // might as well remove it.
9299 if (!dfunc->df_deleted && new_def_function 9313 if (!dfunc->df_deleted && new_def_function