changeset 4679:4d92b873acef v7.3.1087

updated for version 7.3.1087 Problem: A leading star is not seen as a normal char when \{} follows. Solution: Save and restore the parse state properly.
author Bram Moolenaar <bram@vim.org>
date Sat, 01 Jun 2013 14:42:56 +0200
parents 2425a12d8e45
children fd8cc7fbc273
files src/regexp.c src/regexp_nfa.c src/testdir/test64.in src/testdir/test64.ok src/version.c
diffstat 5 files changed, 79 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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;
--- 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'])
--- 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\{}
--- 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,