summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/regexp.c53
-rw-r--r--src/regexp_nfa.c28
-rw-r--r--src/testdir/test64.in4
-rw-r--r--src/testdir/test64.ok9
-rw-r--r--src/version.c2
5 files changed, 79 insertions, 17 deletions
diff --git a/src/regexp.c b/src/regexp.c
index f0b932566..cfeee4c27 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -665,10 +665,25 @@ static int nextchr; /* used for ungetchr() */
#define REG_ZPAREN 2 /* \z(\) */
#define REG_NPAREN 3 /* \%(\) */
+typedef struct
+{
+ char_u *regparse;
+ int prevchr_len;
+ int curchr;
+ int prevchr;
+ int prevprevchr;
+ int nextchr;
+ int at_start;
+ int prev_at_start;
+ int regnpar;
+} parse_state_T;
+
/*
* Forward declarations for vim_regcomp()'s friends.
*/
static void initchr __ARGS((char_u *));
+static void save_parse_state __ARGS((parse_state_T *ps));
+static void restore_parse_state __ARGS((parse_state_T *ps));
static int getchr __ARGS((void));
static void skipchr_keepstart __ARGS((void));
static int peekchr __ARGS((void));
@@ -2951,6 +2966,44 @@ initchr(str)
}
/*
+ * Save the current parse state, so that it can be restored and parsing
+ * starts in the same state again.
+ */
+ static void
+save_parse_state(ps)
+ parse_state_T *ps;
+{
+ ps->regparse = regparse;
+ ps->prevchr_len = prevchr_len;
+ ps->curchr = curchr;
+ ps->prevchr = prevchr;
+ ps->prevprevchr = prevprevchr;
+ ps->nextchr = nextchr;
+ ps->at_start = at_start;
+ ps->prev_at_start = prev_at_start;
+ ps->regnpar = regnpar;
+}
+
+/*
+ * Restore a previously saved parse state.
+ */
+ static void
+restore_parse_state(ps)
+ parse_state_T *ps;
+{
+ regparse = ps->regparse;
+ prevchr_len = ps->prevchr_len;
+ curchr = ps->curchr;
+ prevchr = ps->prevchr;
+ prevprevchr = ps->prevprevchr;
+ nextchr = ps->nextchr;
+ at_start = ps->at_start;
+ prev_at_start = ps->prev_at_start;
+ regnpar = ps->regnpar;
+}
+
+
+/*
* Get the next character without advancing.
*/
static int
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
index 2d1df6d63..fffe4a0cc 100644
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -1318,19 +1318,17 @@ nfa_regpiece()
int ret;
long minval, maxval;
int greedy = TRUE; /* Braces are prefixed with '-' ? */
- char_u *old_regparse, *new_regparse;
+ parse_state_T old_state;
+ parse_state_T new_state;
int c2;
int old_post_pos;
int my_post_start;
- int old_regnpar;
int quest;
- /* Save the current position in the regexp, so that we can use it if
- * <atom>{m,n} is next. */
- old_regparse = regparse;
- /* Save current number of open parenthesis, so we can use it if
- * <atom>{m,n} is next */
- old_regnpar = regnpar;
+ /* Save the current parse state, so that we can use it if <atom>{m,n} is
+ * next. */
+ save_parse_state(&old_state);
+
/* store current pos in the postfix form, for \{m,n} involving 0s */
my_post_start = (int)(post_ptr - post_start);
@@ -1361,8 +1359,7 @@ nfa_regpiece()
* In order to be consistent with the old engine, we replace
* <atom>+ with <atom><atom>*
*/
- regnpar = old_regnpar;
- regparse = old_regparse;
+ restore_parse_state(&old_state);
curchr = -1;
if (nfa_regatom() == FAIL)
return FAIL;
@@ -1452,17 +1449,14 @@ nfa_regpiece()
/* Ignore previous call to nfa_regatom() */
post_ptr = post_start + my_post_start;
- /* Save pos after the repeated atom and the \{} */
- new_regparse = regparse;
+ /* Save parse state after the repeated atom and the \{} */
+ save_parse_state(&new_state);
quest = (greedy == TRUE? NFA_QUEST : NFA_QUEST_NONGREEDY);
for (i = 0; i < maxval; i++)
{
/* Goto beginning of the repeated atom */
- regparse = old_regparse;
- curchr = -1;
- /* Restore count of parenthesis */
- regnpar = old_regnpar;
+ restore_parse_state(&old_state);
old_post_pos = (int)(post_ptr - post_start);
if (nfa_regatom() == FAIL)
return FAIL;
@@ -1486,7 +1480,7 @@ nfa_regpiece()
}
/* Go to just after the repeated atom and the \{} */
- regparse = new_regparse;
+ restore_parse_state(&new_state);
curchr = -1;
break;
diff --git a/src/testdir/test64.in b/src/testdir/test64.in
index 346e792fa..962f60ebe 100644
--- a/src/testdir/test64.in
+++ b/src/testdir/test64.in
@@ -188,6 +188,10 @@ STARTTEST
:call add(tl, [2, 'a\{,0}', 'oidfguih iuhi hiu aaaa', ''])
:call add(tl, [2, 'a\{,5}', 'abcd', 'a'])
:call add(tl, [2, 'a\{,5}', 'aaaaaaaaaa', 'aaaaa'])
+:" leading star as normal char when \{} follows
+:call add(tl, [2, '^*\{4,}$', '***'])
+:call add(tl, [2, '^*\{4,}$', '****', '****'])
+:call add(tl, [2, '^*\{4,}$', '*****', '*****'])
:" same thing as 'a*'
:call add(tl, [2, 'a\{}', 'bbbcddiuhfcd', ''])
:call add(tl, [2, 'a\{}', 'aaaaioudfh coisf jda', 'aaaa'])
diff --git a/src/testdir/test64.ok b/src/testdir/test64.ok
index fdd55da38..b014a16cb 100644
--- a/src/testdir/test64.ok
+++ b/src/testdir/test64.ok
@@ -407,6 +407,15 @@ OK 2 - a\{,5}
OK 0 - a\{,5}
OK 1 - a\{,5}
OK 2 - a\{,5}
+OK 0 - ^*\{4,}$
+OK 1 - ^*\{4,}$
+OK 2 - ^*\{4,}$
+OK 0 - ^*\{4,}$
+OK 1 - ^*\{4,}$
+OK 2 - ^*\{4,}$
+OK 0 - ^*\{4,}$
+OK 1 - ^*\{4,}$
+OK 2 - ^*\{4,}$
OK 0 - a\{}
OK 1 - a\{}
OK 2 - a\{}
diff --git a/src/version.c b/src/version.c
index ec0105e44..641fb6793 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1087,
+/**/
1086,
/**/
1085,