To: vim_dev@googlegroups.com
Subject: Patch 7.3.1153
Fcc: outbox
From: Bram Moolenaar <Bram@moolenaar.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------
Patch 7.3.1153
Problem: New regexp engine: Some look-behind matches are very expensive.
Solution: Pospone invisible matches further, until a match is almost found.
Files: src/regexp_nfa.c
*** ../vim-7.3.1152/src/regexp_nfa.c 2013-06-08 23:30:00.000000000 +0200
--- src/regexp_nfa.c 2013-06-09 16:11:41.000000000 +0200
***************
*** 3354,3369 ****
typedef struct nfa_pim_S nfa_pim_T;
struct nfa_pim_S
{
! nfa_state_T *state;
! int result; /* NFA_PIM_TODO, NFA_PIM_[NO]MATCH */
! nfa_pim_T *pim; /* another PIM at the same position */
regsubs_T subs; /* submatch info, only party used */
};
/* Values for done in nfa_pim_T. */
! #define NFA_PIM_TODO 0
! #define NFA_PIM_MATCH 1
! #define NFA_PIM_NOMATCH -1
/* nfa_thread_T contains execution information of a NFA state */
--- 3354,3374 ----
typedef struct nfa_pim_S nfa_pim_T;
struct nfa_pim_S
{
! int result; /* NFA_PIM_*, see below */
! nfa_state_T *state; /* the invisible match start state */
regsubs_T subs; /* submatch info, only party used */
+ union
+ {
+ lpos_T pos;
+ char_u *ptr;
+ } end; /* where the match must end */
};
/* Values for done in nfa_pim_T. */
! #define NFA_PIM_UNUSED 0 /* pim not used */
! #define NFA_PIM_TODO 1 /* pim not done yet */
! #define NFA_PIM_MATCH 2 /* pim executed, matches */
! #define NFA_PIM_NOMATCH 3 /* pim executed, no match */
/* nfa_thread_T contains execution information of a NFA state */
***************
*** 3371,3377 ****
{
nfa_state_T *state;
int count;
! nfa_pim_T *pim; /* if not NULL: postponed invisible match */
regsubs_T subs; /* submatch info, only party used */
} nfa_thread_T;
--- 3376,3383 ----
{
nfa_state_T *state;
int count;
! nfa_pim_T pim; /* if pim.result != NFA_PIM_UNUSED: postponed
! * invisible match */
regsubs_T subs; /* submatch info, only party used */
} nfa_thread_T;
***************
*** 3424,3434 ****
--- 3430,3457 ----
e == NULL ? "NULL" : e);
}
}
+
+ static char *
+ pim_info(nfa_pim_T *pim)
+ {
+ static char buf[30];
+
+ if (pim == NULL || pim->result == NFA_PIM_UNUSED)
+ buf[0] = NUL;
+ else
+ {
+ sprintf(buf, " PIM col %d", REG_MULTI ? (int)pim->end.pos.col
+ : (int)(pim->end.ptr - reginput));
+ }
+ return buf;
+ }
+
#endif
/* Used during execution: whether a match has been found. */
static int nfa_match;
+ static void copy_pim __ARGS((nfa_pim_T *to, nfa_pim_T *from));
static void clear_sub __ARGS((regsub_T *sub));
static void copy_sub __ARGS((regsub_T *to, regsub_T *from));
static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
***************
*** 3436,3444 ****
static int has_state_with_pos __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
static int match_follows __ARGS((nfa_state_T *startstate, int depth));
static int state_in_list __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
! static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, int off));
static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int *ip));
static void
clear_sub(sub)
regsub_T *sub;
--- 3459,3485 ----
static int has_state_with_pos __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
static int match_follows __ARGS((nfa_state_T *startstate, int depth));
static int state_in_list __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
! static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int off));
static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int *ip));
+ /*
+ * Copy postponed invisible match info from "from" to "to".
+ */
+ static void
+ copy_pim(to, from)
+ nfa_pim_T *to;
+ nfa_pim_T *from;
+ {
+ to->result = from->result;
+ to->state = from->state;
+ copy_sub(&to->subs.norm, &from->subs.norm);
+ #ifdef FEAT_SYN_HL
+ if (nfa_has_zsubexpr)
+ copy_sub(&to->subs.synt, &from->subs.synt);
+ #endif
+ to->end = from->end;
+ }
+
static void
clear_sub(sub)
regsub_T *sub;
***************
*** 3583,3589 ****
#ifdef ENABLE_LOG
static void
! report_state(char *action, regsub_T *sub, nfa_state_T *state, int lid)
{
int col;
--- 3624,3634 ----
#ifdef ENABLE_LOG
static void
! report_state(char *action,
! regsub_T *sub,
! nfa_state_T *state,
! int lid,
! nfa_pim_T *pim)
{
int col;
***************
*** 3594,3601 ****
else
col = (int)(sub->list.line[0].start - regline);
nfa_set_code(state->c);
! fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)\n",
! action, abs(state->id), lid, state->c, code, col);
}
#endif
--- 3639,3647 ----
else
col = (int)(sub->list.line[0].start - regline);
nfa_set_code(state->c);
! fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)%s\n",
! action, abs(state->id), lid, state->c, code, col,
! pim_info(pim));
}
#endif
***************
*** 3646,3651 ****
--- 3692,3701 ----
switch (state->c)
{
case NFA_MATCH:
+ case NFA_MCLOSE:
+ case NFA_END_INVISIBLE:
+ case NFA_END_INVISIBLE_NEG:
+ case NFA_END_PATTERN:
return TRUE;
case NFA_SPLIT:
***************
*** 3727,3736 ****
}
static void
! addstate(l, state, subs, off)
nfa_list_T *l; /* runtime state list */
nfa_state_T *state; /* state to update */
regsubs_T *subs; /* pointers to subexpressions */
int off; /* byte offset, when -1 go to next line */
{
int subidx;
--- 3777,3787 ----
}
static void
! addstate(l, state, subs, pim, off)
nfa_list_T *l; /* runtime state list */
nfa_state_T *state; /* state to update */
regsubs_T *subs; /* pointers to subexpressions */
+ nfa_pim_T *pim; /* postponed look-behind match */
int off; /* byte offset, when -1 go to next line */
{
int subidx;
***************
*** 3856,3876 ****
state->lastlist[nfa_ll_index] = l->id;
thread = &l->t[l->n++];
thread->state = state;
! thread->pim = NULL;
copy_sub(&thread->subs.norm, &subs->norm);
#ifdef FEAT_SYN_HL
if (nfa_has_zsubexpr)
copy_sub(&thread->subs.synt, &subs->synt);
#endif
#ifdef ENABLE_LOG
! report_state("Adding", &thread->subs.norm, state, l->id);
did_print = TRUE;
#endif
}
#ifdef ENABLE_LOG
if (!did_print)
! report_state("Processing", &subs->norm, state, l->id);
#endif
switch (state->c)
{
--- 3907,3930 ----
state->lastlist[nfa_ll_index] = l->id;
thread = &l->t[l->n++];
thread->state = state;
! if (pim == NULL)
! thread->pim.result = NFA_PIM_UNUSED;
! else
! copy_pim(&thread->pim, pim);
copy_sub(&thread->subs.norm, &subs->norm);
#ifdef FEAT_SYN_HL
if (nfa_has_zsubexpr)
copy_sub(&thread->subs.synt, &subs->synt);
#endif
#ifdef ENABLE_LOG
! report_state("Adding", &thread->subs.norm, state, l->id, pim);
did_print = TRUE;
#endif
}
#ifdef ENABLE_LOG
if (!did_print)
! report_state("Processing", &subs->norm, state, l->id, pim);
#endif
switch (state->c)
{
***************
*** 3880,3893 ****
case NFA_SPLIT:
/* order matters here */
! addstate(l, state->out, subs, off);
! addstate(l, state->out1, subs, off);
break;
case NFA_SKIP_CHAR:
case NFA_NOPEN:
case NFA_NCLOSE:
! addstate(l, state->out, subs, off);
break;
case NFA_MOPEN:
--- 3934,3947 ----
case NFA_SPLIT:
/* order matters here */
! addstate(l, state->out, subs, pim, off);
! addstate(l, state->out1, subs, pim, off);
break;
case NFA_SKIP_CHAR:
case NFA_NOPEN:
case NFA_NCLOSE:
! addstate(l, state->out, subs, pim, off);
break;
case NFA_MOPEN:
***************
*** 3983,3989 ****
sub->list.line[subidx].start = reginput + off;
}
! addstate(l, state->out, subs, off);
if (save_in_use == -1)
{
--- 4037,4043 ----
sub->list.line[subidx].start = reginput + off;
}
! addstate(l, state->out, subs, pim, off);
if (save_in_use == -1)
{
***************
*** 4001,4007 ****
{
/* Do not overwrite the position set by \ze. If no \ze
* encountered end will be set in nfa_regtry(). */
! addstate(l, state->out, subs, off);
break;
}
case NFA_MCLOSE1:
--- 4055,4061 ----
{
/* Do not overwrite the position set by \ze. If no \ze
* encountered end will be set in nfa_regtry(). */
! addstate(l, state->out, subs, pim, off);
break;
}
case NFA_MCLOSE1:
***************
*** 4070,4076 ****
sub->list.line[subidx].end = reginput + off;
}
! addstate(l, state->out, subs, off);
if (REG_MULTI)
sub->list.multi[subidx].end = save_lpos;
--- 4124,4130 ----
sub->list.line[subidx].end = reginput + off;
}
! addstate(l, state->out, subs, pim, off);
if (REG_MULTI)
sub->list.multi[subidx].end = save_lpos;
***************
*** 4098,4112 ****
int tlen = l->n;
int count;
int listidx = *ip;
- int i;
/* first add the state(s) at the end, so that we know how many there are */
! addstate(l, state, subs, 0);
!
! /* fill in the "pim" field in the new states */
! if (pim != NULL)
! for (i = tlen; i < l->n; ++i)
! l->t[i].pim = pim;
/* when "*ip" was at the end of the list, nothing to do */
if (listidx + 1 == tlen)
--- 4152,4160 ----
int tlen = l->n;
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);
/* when "*ip" was at the end of the list, nothing to do */
if (listidx + 1 == tlen)
***************
*** 4355,4369 ****
return val == pos;
}
! static int recursive_regmatch __ARGS((nfa_state_T *state, nfa_regprog_T *prog, regsubs_T *submatch, regsubs_T *m, int **listids));
static int nfa_regmatch __ARGS((nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *submatch, regsubs_T *m));
/*
* Recursively call nfa_regmatch()
*/
static int
! recursive_regmatch(state, prog, submatch, m, listids)
nfa_state_T *state;
nfa_regprog_T *prog;
regsubs_T *submatch;
regsubs_T *m;
--- 4403,4420 ----
return val == pos;
}
! static int recursive_regmatch __ARGS((nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T *prog, regsubs_T *submatch, regsubs_T *m, int **listids));
static int nfa_regmatch __ARGS((nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *submatch, regsubs_T *m));
/*
* Recursively call nfa_regmatch()
+ * "pim" is NULL or contains info about a Postponed Invisible Match (start
+ * position).
*/
static int
! recursive_regmatch(state, pim, prog, submatch, m, listids)
nfa_state_T *state;
+ nfa_pim_T *pim;
nfa_regprog_T *prog;
regsubs_T *submatch;
regsubs_T *m;
***************
*** 4380,4397 ****
int result;
int need_restore = FALSE;
if (state->c == NFA_START_INVISIBLE_BEFORE
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG)
{
! /* The recursive match must end at the current position. */
endposp = &endpos;
if (REG_MULTI)
{
! endpos.se_u.pos.col = (int)(reginput - regline);
! endpos.se_u.pos.lnum = reglnum;
}
else
! endpos.se_u.ptr = reginput;
/* Go back the specified number of bytes, or as far as the
* start of the previous line, to try matching "\@<=" or
--- 4431,4468 ----
int result;
int need_restore = FALSE;
+ if (pim != NULL)
+ {
+ /* start at the position where the postponed match was */
+ if (REG_MULTI)
+ reginput = regline + pim->end.pos.col;
+ else
+ reginput = pim->end.ptr;
+ }
+
if (state->c == NFA_START_INVISIBLE_BEFORE
|| state->c == NFA_START_INVISIBLE_BEFORE_NEG)
{
! /* The recursive match must end at the current position. When "pim" is
! * not NULL it specifies the current position. */
endposp = &endpos;
if (REG_MULTI)
{
! if (pim == NULL)
! {
! endpos.se_u.pos.col = (int)(reginput - regline);
! endpos.se_u.pos.lnum = reglnum;
! }
! else
! endpos.se_u.pos = pim->end.pos;
}
else
! {
! if (pim == NULL)
! endpos.se_u.ptr = reginput;
! else
! endpos.se_u.ptr = pim->end.ptr;
! }
/* Go back the specified number of bytes, or as far as the
* start of the previous line, to try matching "\@<=" or
***************
*** 4784,4790 ****
int add_here;
int add_count;
int add_off;
- garray_T pimlist;
int toplevel = start->c == NFA_MOPEN;
#ifdef NFA_REGEXP_DEBUG_LOG
FILE *debug = fopen(NFA_REGEXP_DEBUG_LOG, "a");
--- 4855,4860 ----
***************
*** 4796,4802 ****
}
#endif
nfa_match = FALSE;
- ga_init2(&pimlist, sizeof(nfa_pim_T), 5);
/* Allocate memory for the lists of nodes. */
size = (nstate + 1) * sizeof(nfa_thread_T);
--- 4866,4871 ----
***************
*** 4845,4854 ****
else
m->norm.list.line[0].start = reginput;
m->norm.in_use = 1;
! addstate(thislist, start->out, m, 0);
}
else
! addstate(thislist, start, m, 0);
#define ADD_STATE_IF_MATCH(state) \
if (result) { \
--- 4914,4923 ----
else
m->norm.list.line[0].start = reginput;
m->norm.in_use = 1;
! addstate(thislist, start->out, m, NULL, 0);
}
else
! addstate(thislist, start, m, NULL, 0);
#define ADD_STATE_IF_MATCH(state) \
if (result) { \
***************
*** 4890,4897 ****
thislist->id = nfa_listid;
nextlist->id = nfa_listid + 1;
- pimlist.ga_len = 0;
-
#ifdef ENABLE_LOG
fprintf(log_fd, "------------------------------------------\n");
fprintf(log_fd, ">>> Reginput is \"%s\"\n", reginput);
--- 4959,4964 ----
***************
*** 4935,4942 ****
else
col = (int)(t->subs.norm.list.line[0].start - regline);
nfa_set_code(t->state->c);
! fprintf(log_fd, "(%d) char %d %s (start col %d) ... \n",
! abs(t->state->id), (int)t->state->c, code, col);
}
#endif
--- 5002,5010 ----
else
col = (int)(t->subs.norm.list.line[0].start - regline);
nfa_set_code(t->state->c);
! fprintf(log_fd, "(%d) char %d %s (start col %d)%s ... \n",
! abs(t->state->id), (int)t->state->c, code, col,
! pim_info(&t->pim));
}
#endif
***************
*** 5028,5048 ****
case NFA_START_INVISIBLE_BEFORE:
case NFA_START_INVISIBLE_BEFORE_NEG:
{
- nfa_pim_T *pim;
int cout = t->state->out1->out->c;
/* Do it directly when what follows is possibly end of
* match (closing paren).
* Postpone when it is \@<= or \@<!, these are expensive.
- * TODO: remove the check for t->pim and check multiple
- * where it's used?
* Otherwise first do the one that has the highest chance
* of failing. */
if ((cout >= NFA_MCLOSE && cout <= NFA_MCLOSE9)
#ifdef FEAT_SYN_HL
|| (cout >= NFA_ZCLOSE && cout <= NFA_ZCLOSE9)
#endif
! || t->pim != NULL
|| (t->state->c != NFA_START_INVISIBLE_BEFORE
&& t->state->c != NFA_START_INVISIBLE_BEFORE_NEG
&& failure_chance(t->state->out1->out, 0)
--- 5096,5114 ----
case NFA_START_INVISIBLE_BEFORE:
case NFA_START_INVISIBLE_BEFORE_NEG:
{
int cout = t->state->out1->out->c;
/* Do it directly when what follows is possibly end of
* match (closing paren).
+ * Do it directly if there already is a PIM.
* Postpone when it is \@<= or \@<!, these are expensive.
* Otherwise first do the one that has the highest chance
* of failing. */
if ((cout >= NFA_MCLOSE && cout <= NFA_MCLOSE9)
#ifdef FEAT_SYN_HL
|| (cout >= NFA_ZCLOSE && cout <= NFA_ZCLOSE9)
#endif
! || t->pim.result != NFA_PIM_UNUSED
|| (t->state->c != NFA_START_INVISIBLE_BEFORE
&& t->state->c != NFA_START_INVISIBLE_BEFORE_NEG
&& failure_chance(t->state->out1->out, 0)
***************
*** 5052,5058 ****
* First try matching the invisible match, then what
* follows.
*/
! result = recursive_regmatch(t->state, prog,
submatch, m, &listids);
/* for \@! and \@<! it is a match when the result is
--- 5118,5124 ----
* First try matching the invisible match, then what
* follows.
*/
! result = recursive_regmatch(t->state, NULL, prog,
submatch, m, &listids);
/* for \@! and \@<! it is a match when the result is
***************
*** 5077,5102 ****
}
else
{
/*
! * First try matching what follows at the current
! * position. Only if a match is found, before
! * addstate() is called, then verify the invisible
! * match matches. Add a nfa_pim_T to the following
! * states, it contains info about the invisible match.
*/
! if (ga_grow(&pimlist, 1) == FAIL)
! goto theend;
! pim = (nfa_pim_T *)pimlist.ga_data + pimlist.ga_len;
! ++pimlist.ga_len;
! pim->state = t->state;
! pim->pim = NULL;
! pim->result = NFA_PIM_TODO;
/* t->state->out1 is the corresponding END_INVISIBLE
* node; Add its out to the current list (zero-width
* match). */
addstate_here(thislist, t->state->out1->out, &t->subs,
! pim, &listidx);
}
}
break;
--- 5143,5175 ----
}
else
{
+ nfa_pim_T pim;
+
/*
! * First try matching what follows. Only if a match
! * is found verify the invisible match matches. Add a
! * nfa_pim_T to the following states, it contains info
! * about the invisible match.
*/
! pim.state = t->state;
! pim.result = NFA_PIM_TODO;
! pim.subs.norm.in_use = 0;
! #ifdef FEAT_SYN_HL
! pim.subs.synt.in_use = 0;
! #endif
! if (REG_MULTI)
! {
! pim.end.pos.col = (int)(reginput - regline);
! pim.end.pos.lnum = reglnum;
! }
! else
! pim.end.ptr = reginput;
/* t->state->out1 is the corresponding END_INVISIBLE
* node; Add its out to the current list (zero-width
* match). */
addstate_here(thislist, t->state->out1->out, &t->subs,
! &pim, &listidx);
}
}
break;
***************
*** 5144,5150 ****
}
/* First try matching the pattern. */
! result = recursive_regmatch(t->state, prog,
submatch, m, &listids);
if (result)
{
--- 5217,5223 ----
}
/* First try matching the pattern. */
! result = recursive_regmatch(t->state, NULL, prog,
submatch, m, &listids);
if (result)
{
***************
*** 5798,5809 ****
if (add_state != NULL)
{
! /* Handle the postponed invisible match before advancing to
! * the next character and for a zero-width match if the match
! * might end without advancing. */
! if (t->pim != NULL && (!add_here || match_follows(add_state, 0)))
{
! if (t->pim->result == NFA_PIM_TODO)
{
#ifdef ENABLE_LOG
fprintf(log_fd, "\n");
--- 5871,5888 ----
if (add_state != NULL)
{
! nfa_pim_T *pim;
!
! if (t->pim.result == NFA_PIM_UNUSED)
! pim = NULL;
! else
! pim = &t->pim;
!
! /* Handle the postponed invisible match if the match might end
! * without advancing and before the end of the line. */
! if (pim != NULL && (clen == 0 || match_follows(add_state, 0)))
{
! if (pim->result == NFA_PIM_TODO)
{
#ifdef ENABLE_LOG
fprintf(log_fd, "\n");
***************
*** 5811,5868 ****
fprintf(log_fd, "Postponed recursive nfa_regmatch()\n");
fprintf(log_fd, "\n");
#endif
! result = recursive_regmatch(t->pim->state,
prog, submatch, m, &listids);
! t->pim->result = result ? NFA_PIM_MATCH
! : NFA_PIM_NOMATCH;
/* for \@! and \@<! it is a match when the result is
* FALSE */
! if (result != (t->pim->state->c
! == NFA_START_INVISIBLE_NEG
! || t->pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG))
{
/* Copy submatch info from the recursive call */
! copy_sub_off(&t->pim->subs.norm, &m->norm);
#ifdef FEAT_SYN_HL
if (nfa_has_zsubexpr)
! copy_sub_off(&t->pim->subs.synt, &m->synt);
#endif
}
}
else
{
! result = (t->pim->result == NFA_PIM_MATCH);
#ifdef ENABLE_LOG
fprintf(log_fd, "\n");
! fprintf(log_fd, "Using previous recursive nfa_regmatch() result, result == %d\n", t->pim->result);
fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
fprintf(log_fd, "\n");
#endif
}
/* for \@! and \@<! it is a match when result is FALSE */
! if (result != (t->pim->state->c == NFA_START_INVISIBLE_NEG
! || t->pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG))
{
/* Copy submatch info from the recursive call */
! copy_sub_off(&t->subs.norm, &t->pim->subs.norm);
#ifdef FEAT_SYN_HL
if (nfa_has_zsubexpr)
! copy_sub_off(&t->subs.synt, &t->pim->subs.synt);
#endif
}
else
/* look-behind match failed, don't add the state */
continue;
}
if (add_here)
! addstate_here(thislist, add_state, &t->subs, t->pim, &listidx);
else
{
! addstate(nextlist, add_state, &t->subs, add_off);
if (add_count > 0)
nextlist->t[nextlist->n - 1].count = add_count;
}
--- 5890,5949 ----
fprintf(log_fd, "Postponed recursive nfa_regmatch()\n");
fprintf(log_fd, "\n");
#endif
! result = recursive_regmatch(pim->state, pim,
prog, submatch, m, &listids);
! pim->result = result ? NFA_PIM_MATCH : NFA_PIM_NOMATCH;
/* for \@! and \@<! it is a match when the result is
* FALSE */
! if (result != (pim->state->c == NFA_START_INVISIBLE_NEG
! || pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG))
{
/* Copy submatch info from the recursive call */
! copy_sub_off(&pim->subs.norm, &m->norm);
#ifdef FEAT_SYN_HL
if (nfa_has_zsubexpr)
! copy_sub_off(&pim->subs.synt, &m->synt);
#endif
}
}
else
{
! result = (pim->result == NFA_PIM_MATCH);
#ifdef ENABLE_LOG
fprintf(log_fd, "\n");
! fprintf(log_fd, "Using previous recursive nfa_regmatch() result, result == %d\n", pim->result);
fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
fprintf(log_fd, "\n");
#endif
}
/* for \@! and \@<! it is a match when result is FALSE */
! if (result != (pim->state->c == NFA_START_INVISIBLE_NEG
! || pim->state->c
== NFA_START_INVISIBLE_BEFORE_NEG))
{
/* Copy submatch info from the recursive call */
! copy_sub_off(&t->subs.norm, &pim->subs.norm);
#ifdef FEAT_SYN_HL
if (nfa_has_zsubexpr)
! copy_sub_off(&t->subs.synt, &pim->subs.synt);
#endif
}
else
/* look-behind match failed, don't add the state */
continue;
+
+ /* Postponed invisible match was handled, don't add it to
+ * following states. */
+ pim = NULL;
}
if (add_here)
! addstate_here(thislist, add_state, &t->subs, pim, &listidx);
else
{
! addstate(nextlist, add_state, &t->subs, pim, add_off);
if (add_count > 0)
nextlist->t[nextlist->n - 1].count = add_count;
}
***************
*** 5941,5951 ****
(colnr_T)(reginput - regline) + clen;
else
m->norm.list.line[0].start = reginput + clen;
! addstate(nextlist, start->out, m, clen);
}
}
else
! addstate(nextlist, start, m, clen);
}
#ifdef ENABLE_LOG
--- 6022,6032 ----
(colnr_T)(reginput - regline) + clen;
else
m->norm.list.line[0].start = reginput + clen;
! addstate(nextlist, start->out, m, NULL, clen);
}
}
else
! addstate(nextlist, start, m, NULL, clen);
}
#ifdef ENABLE_LOG
***************
*** 5982,5988 ****
vim_free(list[0].t);
vim_free(list[1].t);
vim_free(listids);
- ga_clear(&pimlist);
#undef ADD_STATE_IF_MATCH
#ifdef NFA_REGEXP_DEBUG_LOG
fclose(debug);
--- 6063,6068 ----
*** ../vim-7.3.1152/src/version.c 2013-06-08 23:30:00.000000000 +0200
--- src/version.c 2013-06-09 15:21:03.000000000 +0200
***************
*** 730,731 ****
--- 730,733 ----
{ /* Add new patch number below this line */
+ /**/
+ 1153,
/**/
--
"Computers in the future may weigh no more than 1.5 tons."
Popular Mechanics, 1949
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///