summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-09-09 20:29:50 +0200
committerBram Moolenaar <Bram@vim.org>2016-09-09 20:29:50 +0200
commit16b3578f355282846f2600ce77fb344950f0b9ce (patch)
tree2e0c8306d33dfbb9e904510e3dea3a5bcb50512a /src
parentd563883a1fb5ec6cf4a2758c5e36ac1ff4e9bb3d (diff)
patch 7.4.2355v7.4.2355
Problem: Regexp fails to match when using "\>\)\?". (Ramel) Solution: When a state is already in the list, but addstate_here() is used and the existing state comes later, add the new state anyway.
Diffstat (limited to 'src')
-rw-r--r--src/regexp_nfa.c58
-rw-r--r--src/testdir/test_regexp_latin.vim9
-rw-r--r--src/version.c2
3 files changed, 56 insertions, 13 deletions
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
index f8ce4e99a4..1f331aed40 100644
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -4340,6 +4340,9 @@ state_in_list(
return FALSE;
}
+/* Offset used for "off" by addstate_here(). */
+#define ADDSTATE_HERE_OFFSET 10
+
/*
* Add "state" and possibly what follows to state list ".".
* Returns "subs_arg", possibly copied into temp_subs.
@@ -4350,9 +4353,14 @@ addstate(
nfa_state_T *state, /* state to update */
regsubs_T *subs_arg, /* pointers to subexpressions */
nfa_pim_T *pim, /* postponed look-behind match */
- int off) /* byte offset, when -1 go to next line */
+ int off_arg) /* byte offset, when -1 go to next line */
{
int subidx;
+ int off = off_arg;
+ int add_here = FALSE;
+ int listindex = 0;
+ int k;
+ int found = FALSE;
nfa_thread_T *thread;
struct multipos save_multipos;
int save_in_use;
@@ -4365,6 +4373,13 @@ addstate(
int did_print = FALSE;
#endif
+ if (off_arg <= -ADDSTATE_HERE_OFFSET)
+ {
+ add_here = TRUE;
+ off = 0;
+ listindex = -(off_arg + ADDSTATE_HERE_OFFSET);
+ }
+
switch (state->c)
{
case NFA_NCLOSE:
@@ -4448,13 +4463,28 @@ addstate(
if (!nfa_has_backref && pim == NULL && !l->has_pim
&& state->c != NFA_MATCH)
{
+ /* When called from addstate_here() do insert before
+ * existing states. */
+ if (add_here)
+ {
+ for (k = 0; k < l->n && k < listindex; ++k)
+ if (l->t[k].state->id == state->id)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!add_here || found)
+ {
skip_add:
#ifdef ENABLE_LOG
- nfa_set_code(state->c);
- fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s\n",
- abs(state->id), l->id, state->c, code);
+ nfa_set_code(state->c);
+ fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s pim: %s has_pim: %d found: %d\n",
+ abs(state->id), l->id, state->c, code,
+ pim == NULL ? "NULL" : "yes", l->has_pim, found);
#endif
- return subs;
+ return subs;
+ }
}
/* Do not add the state again when it exists with the same
@@ -4519,14 +4549,14 @@ skip_add:
case NFA_SPLIT:
/* order matters here */
- subs = addstate(l, state->out, subs, pim, off);
- subs = addstate(l, state->out1, subs, pim, off);
+ subs = addstate(l, state->out, subs, pim, off_arg);
+ subs = addstate(l, state->out1, subs, pim, off_arg);
break;
case NFA_EMPTY:
case NFA_NOPEN:
case NFA_NCLOSE:
- subs = addstate(l, state->out, subs, pim, off);
+ subs = addstate(l, state->out, subs, pim, off_arg);
break;
case NFA_MOPEN:
@@ -4626,7 +4656,7 @@ skip_add:
sub->list.line[subidx].start = reginput + off;
}
- subs = addstate(l, state->out, subs, pim, off);
+ subs = addstate(l, state->out, subs, pim, off_arg);
/* "subs" may have changed, need to set "sub" again */
#ifdef FEAT_SYN_HL
if (state->c >= NFA_ZOPEN && state->c <= NFA_ZOPEN9)
@@ -4652,7 +4682,7 @@ skip_add:
: subs->norm.list.line[0].end != NULL))
{
/* Do not overwrite the position set by \ze. */
- subs = addstate(l, state->out, subs, pim, off);
+ subs = addstate(l, state->out, subs, pim, off_arg);
break;
}
case NFA_MCLOSE1:
@@ -4725,7 +4755,7 @@ skip_add:
vim_memset(&save_multipos, 0, sizeof(save_multipos));
}
- subs = addstate(l, state->out, subs, pim, off);
+ subs = addstate(l, state->out, subs, pim, off_arg);
/* "subs" may have changed, need to set "sub" again */
#ifdef FEAT_SYN_HL
if (state->c >= NFA_ZCLOSE && state->c <= NFA_ZCLOSE9)
@@ -4762,8 +4792,10 @@ addstate_here(
int count;
int listidx = *ip;
- /* first add the state(s) at the end, so that we know how many there are */
- addstate(l, state, subs, pim, 0);
+ /* First add the state(s) at the end, so that we know how many there are.
+ * Pass the listidx as offset (avoids adding another argument to
+ * addstate(). */
+ addstate(l, state, subs, pim, -listidx - ADDSTATE_HERE_OFFSET);
/* when "*ip" was at the end of the list, nothing to do */
if (listidx + 1 == tlen)
diff --git a/src/testdir/test_regexp_latin.vim b/src/testdir/test_regexp_latin.vim
index 15ff4f9e4e..247e5e65ab 100644
--- a/src/testdir/test_regexp_latin.vim
+++ b/src/testdir/test_regexp_latin.vim
@@ -53,3 +53,12 @@ func Test_nested_backrefs()
bwipe!
set re=0
endfunc
+
+func Test_eow_with_optional()
+ let expected = ['abc def', 'abc', 'def', '', '', '', '', '', '', '']
+ for re in range(0, 2)
+ exe 'set re=' . re
+ let actual = matchlist('abc def', '\(abc\>\)\?\s*\(def\)')
+ call assert_equal(expected, actual)
+ endfor
+endfunc
diff --git a/src/version.c b/src/version.c
index ff5076fc3f..f332e43e9b 100644
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2355,
+/**/
2354,
/**/
2353,