From 45ca7d4a62d9d6275339e9d9c0a4930448592712 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 11:17:10 +0800 Subject: vim-patch:8.2.0502: Vim9: some code is not tested Problem: Vim9: some code is not tested. Solution: Add more tests. Fix uncovered problems. https://github.com/vim/vim/commit/e8c4abbbd711af8fd3ed85ea69e9ac3d63a0d879 Co-authored-by: Bram Moolenaar --- src/nvim/cmdexpand.c | 4 ++-- src/nvim/eval/userfunc.c | 2 +- src/nvim/ex_cmds.c | 8 ++++---- src/nvim/ex_docmd.c | 4 ++-- src/nvim/ex_eval.c | 2 +- src/nvim/ex_getln.c | 2 +- src/nvim/match.c | 2 +- src/nvim/regexp.c | 12 +++++++++++- src/nvim/search.c | 2 +- src/nvim/syntax.c | 4 ++-- src/nvim/tag.c | 4 ++-- 11 files changed, 28 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c index ca95a9a24e..480f3aa18c 100644 --- a/src/nvim/cmdexpand.c +++ b/src/nvim/cmdexpand.c @@ -1246,7 +1246,7 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons arg = (const char *)skipwhite(skiptowhite(arg)); if (*arg != NUL) { xp->xp_context = EXPAND_NOTHING; - arg = (const char *)skip_regexp((char *)arg + 1, (uint8_t)(*arg), p_magic, NULL); + arg = (const char *)skip_regexp((char *)arg + 1, (uint8_t)(*arg), p_magic); } } return (const char *)find_nextcmd(arg); @@ -1285,7 +1285,7 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, cons if (delim) { // Skip "from" part. arg++; - arg = (const char *)skip_regexp((char *)arg, delim, p_magic, NULL); + arg = (const char *)skip_regexp((char *)arg, delim, p_magic); } // Skip "to" part. while (arg[0] != NUL && (uint8_t)arg[0] != delim) { diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 71f33fe465..4024410a04 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1964,7 +1964,7 @@ void ex_function(exarg_T *eap) // ":function /pat": list functions matching pattern. if (*eap->arg == '/') { - p = skip_regexp(eap->arg + 1, '/', true, NULL); + p = skip_regexp(eap->arg + 1, '/', true); if (!eap->skip) { regmatch_T regmatch; diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 87c4f4e654..e79a587000 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -504,7 +504,7 @@ void ex_sort(exarg_T *eap) eap->nextcmd = check_nextcmd(p); break; } else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) { - s = skip_regexp(p + 1, *p, true, NULL); + s = skip_regexp(p + 1, *p, true); if (*s != *p) { emsg(_(e_invalpat)); goto sortend; @@ -3503,7 +3503,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T which_pat = RE_LAST; // use last used regexp delimiter = (char_u)(*cmd++); // remember delimiter character pat = cmd; // remember start of search pat - cmd = skip_regexp(cmd, delimiter, p_magic, &eap->arg); + cmd = skip_regexp_ex(cmd, delimiter, p_magic, &eap->arg, NULL); if (cmd[0] == delimiter) { // end delimiter found *cmd++ = NUL; // replace it with a NUL has_second_delim = true; @@ -4536,7 +4536,7 @@ void ex_global(exarg_T *eap) delim = *cmd; // get the delimiter cmd++; // skip delimiter if there is one pat = cmd; // remember start of pattern - cmd = skip_regexp(cmd, delim, p_magic, &eap->arg); + cmd = skip_regexp_ex(cmd, delim, p_magic, &eap->arg, NULL); if (cmd[0] == delim) { // end delimiter found *cmd++ = NUL; // replace it with a NUL } @@ -4849,7 +4849,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags) *s = p + 1; } c = (char_u)(*p); - p = skip_regexp(p + 1, c, true, NULL); + p = skip_regexp(p + 1, c, true); if (*p != c) { return NULL; } diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index d1a1b496f4..dad656d8b6 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -3351,7 +3351,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int goto error; } if (skip) { // skip "/pat/" - cmd = skip_regexp(cmd, c, p_magic, NULL); + cmd = skip_regexp(cmd, c, p_magic); if (*cmd == c) { cmd++; } @@ -6494,7 +6494,7 @@ static void ex_findpat(exarg_T *eap) if (*eap->arg == '/') { // Match regexp, not just whole words whole = false; eap->arg++; - char *p = skip_regexp(eap->arg, '/', p_magic, NULL); + char *p = skip_regexp(eap->arg, '/', p_magic); if (*p) { *p++ = NUL; p = skipwhite(p); diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 2d6b236007..761c0770b6 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -1296,7 +1296,7 @@ void ex_catch(exarg_T *eap) eap->nextcmd = find_nextcmd(eap->arg); } else { pat = eap->arg + 1; - end = skip_regexp(pat, *eap->arg, true, NULL); + end = skip_regexp(pat, *eap->arg, true); } if (!give_up) { diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index a1e4bc96b5..1d242e4ed2 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -314,7 +314,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s p = skipwhite(p); delim = (delim_optional && vim_isIDc(*p)) ? ' ' : *p++; *search_delim = delim; - end = skip_regexp(p, delim, p_magic, NULL); + end = skip_regexp(p, delim, p_magic); use_last_pat = end == p && *end == delim; if (end == p && !use_last_pat) { diff --git a/src/nvim/match.c b/src/nvim/match.c index b422dc0ba8..916bb44d8c 100644 --- a/src/nvim/match.c +++ b/src/nvim/match.c @@ -1206,7 +1206,7 @@ void ex_match(exarg_T *eap) semsg(_(e_invarg2), eap->arg); return; } - end = skip_regexp(p + 1, *p, true, NULL); + end = skip_regexp(p + 1, *p, true); if (!eap->skip) { if (*end != NUL && !ends_excmd(*skipwhite(end + 1))) { xfree(g); diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index d6f207a248..4ae7fc7578 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -484,10 +484,17 @@ static char_u *skip_anyof(char *p) /// Stop at end of "startp" or where "dirc" is found ('/', '?', etc). /// Take care of characters with a backslash in front of it. /// Skip strings inside [ and ]. +char *skip_regexp(char *startp, int dirc, int magic) +{ + return skip_regexp_ex(startp, dirc, magic, NULL, NULL); +} + +/// skip_regexp() with extra arguments: /// When "newp" is not NULL and "dirc" is '?', make an allocated copy of the /// expression and change "\?" to "?". If "*newp" is not NULL the expression /// is changed in-place. -char *skip_regexp(char *startp, int dirc, int magic, char **newp) +/// If a "\?" is changed to "?" then "dropped" is incremented, unless NULL. +char *skip_regexp_ex(char *startp, int dirc, int magic, char **newp, int *dropped) { int mymagic; char *p = startp; @@ -516,6 +523,9 @@ char *skip_regexp(char *startp, int dirc, int magic, char **newp) *newp = xstrdup(startp); p = *newp + (p - startp); } + if (dropped != NULL) { + (*dropped)++; + } STRMOVE(p, p + 1); } else { p++; // skip next character diff --git a/src/nvim/search.c b/src/nvim/search.c index 49892a4cc5..2f3e5a2cb6 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -1080,7 +1080,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char_u *pat, long count, // Find end of regular expression. // If there is a matching '/' or '?', toss it. ps = (char_u *)strcopy; - p = (char_u *)skip_regexp((char *)pat, search_delim, p_magic, &strcopy); + p = (char_u *)skip_regexp_ex((char *)pat, search_delim, p_magic, &strcopy, NULL); if (strcopy != (char *)ps) { // made a copy of "pat" to change "\?" to "?" searchcmdlen += (int)(STRLEN(pat) - strlen(strcopy)); diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index e5962cd273..fb82df4fe9 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -4749,7 +4749,7 @@ static char *get_syn_pattern(char *arg, synpat_T *ci) return NULL; } - end = skip_regexp(arg + 1, *arg, true, NULL); + end = skip_regexp(arg + 1, *arg, true); if (*end != *arg) { // end delimiter not found semsg(_("E401: Pattern delimiter not found: %s"), arg); return NULL; @@ -4902,7 +4902,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing) finished = true; break; } - arg_end = skip_regexp(next_arg + 1, *next_arg, true, NULL); + arg_end = skip_regexp(next_arg + 1, *next_arg, true); if (*arg_end != *next_arg) { // end delimiter not found illegal = true; break; diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 90b21320d2..264f961b43 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2670,7 +2670,7 @@ static int jumpto_tag(const char_u *lbuf_arg, int forceit, int keep_help) // anything following. str = pbuf; if (pbuf[0] == '/' || pbuf[0] == '?') { - str = (char_u *)skip_regexp((char *)pbuf + 1, pbuf[0], false, NULL) + 1; + str = (char_u *)skip_regexp((char *)pbuf + 1, pbuf[0], false) + 1; } if (str > pbuf_end - 1) { // search command with nothing following save_p_ws = p_ws; @@ -2883,7 +2883,7 @@ static int find_extra(char_u **pp) if (ascii_isdigit(*str)) { str = (char_u *)skipdigits((char *)str + 1); } else if (*str == '/' || *str == '?') { - str = (char_u *)skip_regexp((char *)str + 1, *str, false, NULL); + str = (char_u *)skip_regexp((char *)str + 1, *str, false); if (*str != first_char) { str = NULL; } else { -- cgit From 199c7c28989a3c36447ef56b71c7b84756950a11 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 11:27:28 +0800 Subject: vim-patch:8.2.0612: Vim9: no check for space before #comment Problem: Vim9: no check for space before #comment. Solution: Add space checks. https://github.com/vim/vim/commit/2c5ed4e3300378ce76c8d9c3818d6f73e5119f68 Omit ends_excmd2(): the same as ends_excmd() in legacy Vim script. Co-authored-by: Bram Moolenaar --- src/nvim/ex_cmds.c | 5 ++--- src/nvim/ex_eval.c | 7 +++++-- src/nvim/highlight_group.c | 2 +- src/nvim/regexp.c | 19 ++++++++++++++++--- src/nvim/testdir/test_sort.vim | 2 +- 5 files changed, 25 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index e79a587000..89e6d47950 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -504,9 +504,8 @@ void ex_sort(exarg_T *eap) eap->nextcmd = check_nextcmd(p); break; } else if (!ASCII_ISALPHA(*p) && regmatch.regprog == NULL) { - s = skip_regexp(p + 1, *p, true); - if (*s != *p) { - emsg(_(e_invalpat)); + s = skip_regexp_err(p + 1, *p, true); + if (s == NULL) { goto sortend; } *s = NUL; diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c index 761c0770b6..8c2ac895cb 100644 --- a/src/nvim/ex_eval.c +++ b/src/nvim/ex_eval.c @@ -900,12 +900,12 @@ void ex_else(exarg_T *eap) if (eap->cmdidx == CMD_elseif) { bool error; result = eval_to_bool(eap->arg, &error, &eap->nextcmd, skip); + // When throwing error exceptions, we want to throw always the first // of several errors in a row. This is what actually happens when // a conditional error was detected above and there is another failure // when parsing the expression. Since the skip flag is set in this // case, the parsing error will be ignored by emsg(). - if (!skip && !error) { if (result) { cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE; @@ -1296,7 +1296,10 @@ void ex_catch(exarg_T *eap) eap->nextcmd = find_nextcmd(eap->arg); } else { pat = eap->arg + 1; - end = skip_regexp(pat, *eap->arg, true); + end = skip_regexp_err(pat, *eap->arg, true); + if (end == NULL) { + give_up = true; + } } if (!give_up) { diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c index 4c253480be..9a09118939 100644 --- a/src/nvim/highlight_group.c +++ b/src/nvim/highlight_group.c @@ -851,7 +851,7 @@ void do_highlight(const char *line, const bool forceit, const bool init) bool did_highlight_changed = false; // If no argument, list current highlighting. - if (ends_excmd((uint8_t)(*line))) { + if (!init && ends_excmd((uint8_t)(*line))) { for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) { // TODO(brammool): only call when the group has attributes set highlight_list_one(i); diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 4ae7fc7578..68ffc70457 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -481,12 +481,25 @@ static char_u *skip_anyof(char *p) } /// Skip past regular expression. -/// Stop at end of "startp" or where "dirc" is found ('/', '?', etc). +/// Stop at end of "startp" or where "delim" is found ('/', '?', etc). /// Take care of characters with a backslash in front of it. /// Skip strings inside [ and ]. -char *skip_regexp(char *startp, int dirc, int magic) +char *skip_regexp(char *startp, int delim, int magic) { - return skip_regexp_ex(startp, dirc, magic, NULL, NULL); + return skip_regexp_ex(startp, delim, magic, NULL, NULL); +} + +/// Call skip_regexp() and when the delimiter does not match give an error and +/// return NULL. +char *skip_regexp_err(char *startp, int delim, int magic) +{ + char *p = skip_regexp(startp, delim, magic); + + if (*p != delim) { + semsg(_("E654: missing delimiter after search pattern: %s"), startp); + return NULL; + } + return p; } /// skip_regexp() with extra arguments: diff --git a/src/nvim/testdir/test_sort.vim b/src/nvim/testdir/test_sort.vim index c3e7788164..f9cbcbb55f 100644 --- a/src/nvim/testdir/test_sort.vim +++ b/src/nvim/testdir/test_sort.vim @@ -1360,7 +1360,7 @@ func Test_sort_cmd() call setline(1, ['line1', 'line2']) call assert_fails('sort no', 'E474:') call assert_fails('sort c', 'E475:') - call assert_fails('sort #pat%', 'E682:') + call assert_fails('sort #pat%', 'E654:') enew! endfunc -- cgit