# HG changeset patch # User Bram Moolenaar # Date 1370090576 -7200 # Node ID 4d92b873acefb69e112fd73b642bfdf7979f1355 # Parent 2425a12d8e4520f4488b1b03499d28f4d3fa23ae 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. diff --git a/src/regexp.c b/src/regexp.c --- 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 --- 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 - * {m,n} is next. */ - old_regparse = regparse; - /* Save current number of open parenthesis, so we can use it if - * {m,n} is next */ - old_regnpar = regnpar; + /* Save the current parse state, so that we can use it if {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 * + with * */ - 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 --- 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 --- 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 --- 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,