Karsten Hopp 3c6980
To: vim_dev@googlegroups.com
Karsten Hopp 3c6980
Subject: Patch 7.3.1110
Karsten Hopp 3c6980
Fcc: outbox
Karsten Hopp 3c6980
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp 3c6980
Mime-Version: 1.0
Karsten Hopp 3c6980
Content-Type: text/plain; charset=UTF-8
Karsten Hopp 3c6980
Content-Transfer-Encoding: 8bit
Karsten Hopp 3c6980
------------
Karsten Hopp 3c6980
Karsten Hopp 3c6980
Patch 7.3.1110
Karsten Hopp 3c6980
Problem:    New regexp matching: Using \@= and the like can be slow.
Karsten Hopp 3c6980
Solution:   Decide whether to first try matching the zero-wdith part or what
Karsten Hopp 3c6980
	    follows, whatever is more likely to fail.
Karsten Hopp 3c6980
Files:	    src/regexp_nfa.c
Karsten Hopp 3c6980
Karsten Hopp 3c6980
Karsten Hopp 3c6980
*** ../vim-7.3.1109/src/regexp_nfa.c	2013-06-03 19:41:01.000000000 +0200
Karsten Hopp 3c6980
--- src/regexp_nfa.c	2013-06-04 14:21:32.000000000 +0200
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 2824,2834 ****
Karsten Hopp 3c6980
--- 2824,2851 ----
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
  } regsubs_T;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
+ /* nfa_pim_T stores a Postponed Invisible Match. */
Karsten Hopp 3c6980
+ typedef struct nfa_pim_S nfa_pim_T;
Karsten Hopp 3c6980
+ struct nfa_pim_S
Karsten Hopp 3c6980
+ {
Karsten Hopp 3c6980
+     nfa_state_T	*state;
Karsten Hopp 3c6980
+     int		result;		/* NFA_PIM_TODO, NFA_PIM_[NO]MATCH */
Karsten Hopp 3c6980
+     nfa_pim_T	*pim;		/* another PIM at the same position */
Karsten Hopp 3c6980
+     regsubs_T	subs;		/* submatch info, only party used */
Karsten Hopp 3c6980
+ };
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+ /* Values for done in nfa_pim_T. */
Karsten Hopp 3c6980
+ #define NFA_PIM_TODO    0
Karsten Hopp 3c6980
+ #define NFA_PIM_MATCH   1
Karsten Hopp 3c6980
+ #define NFA_PIM_NOMATCH -1
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
  /* nfa_thread_T contains execution information of a NFA state */
Karsten Hopp 3c6980
  typedef struct
Karsten Hopp 3c6980
  {
Karsten Hopp 3c6980
      nfa_state_T	*state;
Karsten Hopp 3c6980
      int		count;
Karsten Hopp 3c6980
+     nfa_pim_T	*pim;		/* if not NULL: postponed invisible match */
Karsten Hopp 3c6980
      regsubs_T	subs;		/* submatch info, only party used */
Karsten Hopp 3c6980
  } nfa_thread_T;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 2886,2892 ****
Karsten Hopp 3c6980
  static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
Karsten Hopp 3c6980
  static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
Karsten Hopp 3c6980
  static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, int off));
Karsten Hopp 3c6980
! static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, int *ip));
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      static void
Karsten Hopp 3c6980
  clear_sub(sub)
Karsten Hopp 3c6980
--- 2903,2909 ----
Karsten Hopp 3c6980
  static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
Karsten Hopp 3c6980
  static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
Karsten Hopp 3c6980
  static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, int off));
Karsten Hopp 3c6980
! static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int *ip));
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      static void
Karsten Hopp 3c6980
  clear_sub(sub)
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3032,3038 ****
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
      static void
Karsten Hopp 3c6980
! report_state(char *action, regsub_T *sub, nfa_state_T *state, int lid);
Karsten Hopp 3c6980
  {
Karsten Hopp 3c6980
      int col;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
--- 3049,3055 ----
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
      static void
Karsten Hopp 3c6980
! report_state(char *action, regsub_T *sub, nfa_state_T *state, int lid)
Karsten Hopp 3c6980
  {
Karsten Hopp 3c6980
      int col;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3174,3181 ****
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  	    }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
! 	    /* when there are backreferences the number of states may be (a
Karsten Hopp 3c6980
! 	     * lot) bigger */
Karsten Hopp 3c6980
  	    if (nfa_has_backref && l->n == l->len)
Karsten Hopp 3c6980
  	    {
Karsten Hopp 3c6980
  		int newlen = l->len * 3 / 2 + 50;
Karsten Hopp 3c6980
--- 3191,3198 ----
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  	    }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
! 	    /* when there are backreferences or look-behind matches the number
Karsten Hopp 3c6980
! 	     * of states may be (a lot) bigger */
Karsten Hopp 3c6980
  	    if (nfa_has_backref && l->n == l->len)
Karsten Hopp 3c6980
  	    {
Karsten Hopp 3c6980
  		int newlen = l->len * 3 / 2 + 50;
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3188,3193 ****
Karsten Hopp 3c6980
--- 3205,3211 ----
Karsten Hopp 3c6980
  	    state->lastlist[nfa_ll_index] = l->id;
Karsten Hopp 3c6980
  	    thread = &l->t[l->n++];
Karsten Hopp 3c6980
  	    thread->state = state;
Karsten Hopp 3c6980
+ 	    thread->pim = NULL;
Karsten Hopp 3c6980
  	    copy_sub(&thread->subs.norm, &subs->norm);
Karsten Hopp 3c6980
  #ifdef FEAT_SYN_HL
Karsten Hopp 3c6980
  	    if (nfa_has_zsubexpr)
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3419,3439 ****
Karsten Hopp 3c6980
   * matters for alternatives.
Karsten Hopp 3c6980
   */
Karsten Hopp 3c6980
      static void
Karsten Hopp 3c6980
! addstate_here(l, state, subs, ip)
Karsten Hopp 3c6980
      nfa_list_T		*l;	/* runtime state list */
Karsten Hopp 3c6980
      nfa_state_T		*state;	/* state to update */
Karsten Hopp 3c6980
      regsubs_T		*subs;	/* pointers to subexpressions */
Karsten Hopp 3c6980
      int			*ip;
Karsten Hopp 3c6980
  {
Karsten Hopp 3c6980
      int tlen = l->n;
Karsten Hopp 3c6980
      int count;
Karsten Hopp 3c6980
!     int i = *ip;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /* first add the state(s) at the end, so that we know how many there are */
Karsten Hopp 3c6980
      addstate(l, state, subs, 0);
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /* when "*ip" was at the end of the list, nothing to do */
Karsten Hopp 3c6980
!     if (i + 1 == tlen)
Karsten Hopp 3c6980
  	return;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /* re-order to put the new state at the current position */
Karsten Hopp 3c6980
--- 3437,3464 ----
Karsten Hopp 3c6980
   * matters for alternatives.
Karsten Hopp 3c6980
   */
Karsten Hopp 3c6980
      static void
Karsten Hopp 3c6980
! addstate_here(l, state, subs, pim, ip)
Karsten Hopp 3c6980
      nfa_list_T		*l;	/* runtime state list */
Karsten Hopp 3c6980
      nfa_state_T		*state;	/* state to update */
Karsten Hopp 3c6980
      regsubs_T		*subs;	/* pointers to subexpressions */
Karsten Hopp 3c6980
+     nfa_pim_T		*pim;   /* postponed look-behind match */
Karsten Hopp 3c6980
      int			*ip;
Karsten Hopp 3c6980
  {
Karsten Hopp 3c6980
      int tlen = l->n;
Karsten Hopp 3c6980
      int count;
Karsten Hopp 3c6980
!     int listidx = *ip;
Karsten Hopp 3c6980
!     int i;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /* first add the state(s) at the end, so that we know how many there are */
Karsten Hopp 3c6980
      addstate(l, state, subs, 0);
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
+     /* fill in the "pim" field in the new states */
Karsten Hopp 3c6980
+     if (pim != NULL)
Karsten Hopp 3c6980
+ 	for (i = tlen; i < l->n; ++i)
Karsten Hopp 3c6980
+ 	    l->t[i].pim = pim;
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
      /* when "*ip" was at the end of the list, nothing to do */
Karsten Hopp 3c6980
!     if (listidx + 1 == tlen)
Karsten Hopp 3c6980
  	return;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /* re-order to put the new state at the current position */
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3441,3461 ****
Karsten Hopp 3c6980
      if (count == 1)
Karsten Hopp 3c6980
      {
Karsten Hopp 3c6980
  	/* overwrite the current state */
Karsten Hopp 3c6980
! 	l->t[i] = l->t[l->n - 1];
Karsten Hopp 3c6980
      }
Karsten Hopp 3c6980
      else if (count > 1)
Karsten Hopp 3c6980
      {
Karsten Hopp 3c6980
  	/* make space for new states, then move them from the
Karsten Hopp 3c6980
  	 * end to the current position */
Karsten Hopp 3c6980
! 	mch_memmove(&(l->t[i + count]),
Karsten Hopp 3c6980
! 		&(l->t[i + 1]),
Karsten Hopp 3c6980
! 		sizeof(nfa_thread_T) * (l->n - i - 1));
Karsten Hopp 3c6980
! 	mch_memmove(&(l->t[i]),
Karsten Hopp 3c6980
  		&(l->t[l->n - 1]),
Karsten Hopp 3c6980
  		sizeof(nfa_thread_T) * count);
Karsten Hopp 3c6980
      }
Karsten Hopp 3c6980
      --l->n;
Karsten Hopp 3c6980
!     *ip = i - 1;
Karsten Hopp 3c6980
  }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  /*
Karsten Hopp 3c6980
--- 3466,3486 ----
Karsten Hopp 3c6980
      if (count == 1)
Karsten Hopp 3c6980
      {
Karsten Hopp 3c6980
  	/* overwrite the current state */
Karsten Hopp 3c6980
! 	l->t[listidx] = l->t[l->n - 1];
Karsten Hopp 3c6980
      }
Karsten Hopp 3c6980
      else if (count > 1)
Karsten Hopp 3c6980
      {
Karsten Hopp 3c6980
  	/* make space for new states, then move them from the
Karsten Hopp 3c6980
  	 * end to the current position */
Karsten Hopp 3c6980
! 	mch_memmove(&(l->t[listidx + count]),
Karsten Hopp 3c6980
! 		&(l->t[listidx + 1]),
Karsten Hopp 3c6980
! 		sizeof(nfa_thread_T) * (l->n - listidx - 1));
Karsten Hopp 3c6980
! 	mch_memmove(&(l->t[listidx]),
Karsten Hopp 3c6980
  		&(l->t[l->n - 1]),
Karsten Hopp 3c6980
  		sizeof(nfa_thread_T) * count);
Karsten Hopp 3c6980
      }
Karsten Hopp 3c6980
      --l->n;
Karsten Hopp 3c6980
!     *ip = listidx - 1;
Karsten Hopp 3c6980
  }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  /*
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3834,3839 ****
Karsten Hopp 3c6980
--- 3859,3903 ----
Karsten Hopp 3c6980
      return result;
Karsten Hopp 3c6980
  }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
+ static int failure_chance __ARGS((nfa_state_T *state, int depth));
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+ /*
Karsten Hopp 3c6980
+  * Estimate the chance of a match with "state" failing.
Karsten Hopp 3c6980
+  * NFA_ANY: 1
Karsten Hopp 3c6980
+  * specific character: 99
Karsten Hopp 3c6980
+  */
Karsten Hopp 3c6980
+     static int
Karsten Hopp 3c6980
+ failure_chance(state, depth)
Karsten Hopp 3c6980
+     nfa_state_T *state;
Karsten Hopp 3c6980
+     int		depth;
Karsten Hopp 3c6980
+ {
Karsten Hopp 3c6980
+     int c = state->c;
Karsten Hopp 3c6980
+     int l, r;
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+     /* detect looping */
Karsten Hopp 3c6980
+     if (depth > 4)
Karsten Hopp 3c6980
+ 	return 1;
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+     if (c == NFA_SPLIT)
Karsten Hopp 3c6980
+     {
Karsten Hopp 3c6980
+ 	if (state->out->c == NFA_SPLIT || state->out1->c == NFA_SPLIT)
Karsten Hopp 3c6980
+ 	    return 1;
Karsten Hopp 3c6980
+ 	l = failure_chance(state->out, depth + 1);
Karsten Hopp 3c6980
+ 	r = failure_chance(state->out1, depth + 1);
Karsten Hopp 3c6980
+ 	return l < r ? l : r;
Karsten Hopp 3c6980
+     }
Karsten Hopp 3c6980
+     if (c == NFA_ANY)
Karsten Hopp 3c6980
+ 	return 1;
Karsten Hopp 3c6980
+     if (c > 0)
Karsten Hopp 3c6980
+ 	return 99;
Karsten Hopp 3c6980
+     if ((c >= NFA_MOPEN && c <= NFA_MOPEN9)
Karsten Hopp 3c6980
+ 	    || (c >= NFA_ZOPEN && c <= NFA_ZOPEN9)
Karsten Hopp 3c6980
+ 	    || c == NFA_NOPEN)
Karsten Hopp 3c6980
+ 	return failure_chance(state->out, depth + 1);
Karsten Hopp 3c6980
+     /* something else */
Karsten Hopp 3c6980
+     return 50;
Karsten Hopp 3c6980
+ }
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
  /*
Karsten Hopp 3c6980
   * Main matching routine.
Karsten Hopp 3c6980
   *
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3864,3869 ****
Karsten Hopp 3c6980
--- 3928,3937 ----
Karsten Hopp 3c6980
      nfa_list_T	*nextlist;
Karsten Hopp 3c6980
      nfa_list_T	*neglist;
Karsten Hopp 3c6980
      int		*listids = NULL;
Karsten Hopp 3c6980
+     nfa_state_T *add_state;
Karsten Hopp 3c6980
+     int		 add_count;
Karsten Hopp 3c6980
+     int		 add_off;
Karsten Hopp 3c6980
+     garray_T	pimlist;
Karsten Hopp 3c6980
  #ifdef NFA_REGEXP_DEBUG_LOG
Karsten Hopp 3c6980
      FILE	*debug = fopen(NFA_REGEXP_DEBUG_LOG, "a");
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3874,3879 ****
Karsten Hopp 3c6980
--- 3942,3948 ----
Karsten Hopp 3c6980
      }
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
      nfa_match = FALSE;
Karsten Hopp 3c6980
+     ga_init2(&pimlist, sizeof(nfa_pim_T), 5);
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /* Allocate memory for the lists of nodes. */
Karsten Hopp 3c6980
      size = (nstate + 1) * sizeof(nfa_thread_T);
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3923,3933 ****
Karsten Hopp 3c6980
      listtbl[0][1] = neglist;
Karsten Hopp 3c6980
      listtbl[1][0] = nextlist;
Karsten Hopp 3c6980
      listtbl[1][1] = NULL;
Karsten Hopp 3c6980
! #define	ADD_POS_NEG_STATE(node)						    \
Karsten Hopp 3c6980
!     ll = listtbl[result ? 1 : 0][node->negated];			    \
Karsten Hopp 3c6980
!     if (ll != NULL)							    \
Karsten Hopp 3c6980
! 	addstate(ll, node->out , &t->subs, clen);
Karsten Hopp 3c6980
! 
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /*
Karsten Hopp 3c6980
       * Run for each character.
Karsten Hopp 3c6980
--- 3992,4003 ----
Karsten Hopp 3c6980
      listtbl[0][1] = neglist;
Karsten Hopp 3c6980
      listtbl[1][0] = nextlist;
Karsten Hopp 3c6980
      listtbl[1][1] = NULL;
Karsten Hopp 3c6980
! #define	ADD_POS_NEG_STATE(state)			\
Karsten Hopp 3c6980
!     ll = listtbl[result ? 1 : 0][state->negated];	\
Karsten Hopp 3c6980
!     if (ll != NULL) {					\
Karsten Hopp 3c6980
! 	add_state = state->out;				\
Karsten Hopp 3c6980
! 	add_off = clen;					\
Karsten Hopp 3c6980
!     }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
      /*
Karsten Hopp 3c6980
       * Run for each character.
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 3965,3970 ****
Karsten Hopp 3c6980
--- 4035,4042 ----
Karsten Hopp 3c6980
  	nextlist->id = nfa_listid + 1;
Karsten Hopp 3c6980
  	neglist->id = nfa_listid + 1;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
+ 	pimlist.ga_len = 0;
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  	fprintf(log_fd, "------------------------------------------\n");
Karsten Hopp 3c6980
  	fprintf(log_fd, ">>> Reginput is \"%s\"\n", reginput);
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4024,4029 ****
Karsten Hopp 3c6980
--- 4096,4103 ----
Karsten Hopp 3c6980
  	     * Handle the possible codes of the current state.
Karsten Hopp 3c6980
  	     * The most important is NFA_MATCH.
Karsten Hopp 3c6980
  	     */
Karsten Hopp 3c6980
+ 	    add_state = NULL;
Karsten Hopp 3c6980
+ 	    add_count = 0;
Karsten Hopp 3c6980
  	    switch (t->state->c)
Karsten Hopp 3c6980
  	    {
Karsten Hopp 3c6980
  	    case NFA_MATCH:
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4095,4127 ****
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_START_INVISIBLE:
Karsten Hopp 3c6980
  	    case NFA_START_INVISIBLE_BEFORE:
Karsten Hopp 3c6980
! 		result = recursive_regmatch(t->state, prog, submatch, m,
Karsten Hopp 3c6980
! 								    &listids);
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
! 		/* for \@! it is a match when result is FALSE */
Karsten Hopp 3c6980
! 		if (result != t->state->negated)
Karsten Hopp 3c6980
! 		{
Karsten Hopp 3c6980
! 		    /* Copy submatch info from the recursive call */
Karsten Hopp 3c6980
! 		    copy_sub_off(&t->subs.norm, &m->norm);
Karsten Hopp 3c6980
  #ifdef FEAT_SYN_HL
Karsten Hopp 3c6980
! 		    copy_sub_off(&t->subs.synt, &m->synt);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
! 		    /* t->state->out1 is the corresponding END_INVISIBLE node;
Karsten Hopp 3c6980
! 		     * Add its out to the current list (zero-width match). */
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out1->out, &t->subs,
Karsten Hopp 3c6980
! 								    &listidx);
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_BOL:
Karsten Hopp 3c6980
  		if (reginput == regline)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_EOL:
Karsten Hopp 3c6980
  		if (curc == NUL)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_BOW:
Karsten Hopp 3c6980
--- 4169,4256 ----
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_START_INVISIBLE:
Karsten Hopp 3c6980
  	    case NFA_START_INVISIBLE_BEFORE:
Karsten Hopp 3c6980
! 		/* If invisible match has a higher chance to fail, do it
Karsten Hopp 3c6980
! 		 * right away.  Otherwise postpone it until what follows is
Karsten Hopp 3c6980
! 		 * matching and causes addstate(nextlist, ..) to be called.
Karsten Hopp 3c6980
! 		 * This is indicated by the "pim" field. */
Karsten Hopp 3c6980
! 		{
Karsten Hopp 3c6980
! 		    nfa_pim_T *pim;
Karsten Hopp 3c6980
! 		    int cout = t->state->out1->out->c;
Karsten Hopp 3c6980
! 
Karsten Hopp 3c6980
! 		    /* Do it directly when what follows is possibly end of
Karsten Hopp 3c6980
! 		     * match (closing paren).
Karsten Hopp 3c6980
! 		     * Postpone when it is \@<= or \@
Karsten Hopp 3c6980
! 		     * TODO: remove the check for t->pim and check multiple
Karsten Hopp 3c6980
! 		     * where it's used?
Karsten Hopp 3c6980
! 		     * Otherwise first do the one that has the highest chance
Karsten Hopp 3c6980
! 		     * of failing. */
Karsten Hopp 3c6980
! 		    if ((cout >= NFA_MCLOSE && cout <= NFA_MCLOSE9)
Karsten Hopp 3c6980
! 			    || (cout >= NFA_ZCLOSE && cout <= NFA_ZCLOSE9)
Karsten Hopp 3c6980
! 			    || cout == NFA_NCLOSE
Karsten Hopp 3c6980
! 			    || t->pim != NULL
Karsten Hopp 3c6980
! 			    || (t->state->c != NFA_START_INVISIBLE_BEFORE
Karsten Hopp 3c6980
! 				&& failure_chance(t->state->out1->out, 0)
Karsten Hopp 3c6980
! 					  < failure_chance(t->state->out, 0)))
Karsten Hopp 3c6980
! 		    {
Karsten Hopp 3c6980
! 			/*
Karsten Hopp 3c6980
! 			 * First try matching the invisible match, then what
Karsten Hopp 3c6980
! 			 * follows.
Karsten Hopp 3c6980
! 			 */
Karsten Hopp 3c6980
! 			result = recursive_regmatch(t->state, prog,
Karsten Hopp 3c6980
! 						       submatch, m, &listids);
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
! 			/* for \@! it is a match when result is FALSE */
Karsten Hopp 3c6980
! 			if (result != t->state->negated)
Karsten Hopp 3c6980
! 			{
Karsten Hopp 3c6980
! 			    /* Copy submatch info from the recursive call */
Karsten Hopp 3c6980
! 			    copy_sub_off(&t->subs.norm, &m->norm);
Karsten Hopp 3c6980
  #ifdef FEAT_SYN_HL
Karsten Hopp 3c6980
! 			    copy_sub_off(&t->subs.synt, &m->synt);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
! 			    /* t->state->out1 is the corresponding
Karsten Hopp 3c6980
! 			     * END_INVISIBLE node; Add its out to the current
Karsten Hopp 3c6980
! 			     * list (zero-width match). */
Karsten Hopp 3c6980
! 			    addstate_here(thislist, t->state->out1->out,
Karsten Hopp 3c6980
! 						  &t->subs, t->pim, &listidx);
Karsten Hopp 3c6980
! 			}
Karsten Hopp 3c6980
! 		    }
Karsten Hopp 3c6980
! 		    else
Karsten Hopp 3c6980
! 		    {
Karsten Hopp 3c6980
! 			/*
Karsten Hopp 3c6980
! 			 * First try matching what follows at the current
Karsten Hopp 3c6980
! 			 * position.  Only if a match is found, addstate() is
Karsten Hopp 3c6980
! 			 * called, then verify the invisible match matches.
Karsten Hopp 3c6980
! 			 * Add a nfa_pim_T to the following states, it
Karsten Hopp 3c6980
! 			 * contains info about the invisible match.
Karsten Hopp 3c6980
! 			 */
Karsten Hopp 3c6980
! 			if (ga_grow(&pimlist, 1) == FAIL)
Karsten Hopp 3c6980
! 			    goto theend;
Karsten Hopp 3c6980
! 			pim = (nfa_pim_T *)pimlist.ga_data + pimlist.ga_len;
Karsten Hopp 3c6980
! 			++pimlist.ga_len;
Karsten Hopp 3c6980
! 			pim->state = t->state;
Karsten Hopp 3c6980
! 			pim->pim = NULL;
Karsten Hopp 3c6980
! 			pim->result = NFA_PIM_TODO;
Karsten Hopp 3c6980
! 
Karsten Hopp 3c6980
! 			/* t->state->out1 is the corresponding END_INVISIBLE
Karsten Hopp 3c6980
! 			 * node; Add its out to the current list (zero-width
Karsten Hopp 3c6980
! 			 * match). */
Karsten Hopp 3c6980
! 			addstate_here(thislist, t->state->out1->out, &t->subs,
Karsten Hopp 3c6980
! 							       pim, &listidx);
Karsten Hopp 3c6980
! 		    }
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_BOL:
Karsten Hopp 3c6980
  		if (reginput == regline)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_EOL:
Karsten Hopp 3c6980
  		if (curc == NUL)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_BOW:
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4148,4154 ****
Karsten Hopp 3c6980
  				   && vim_iswordc_buf(reginput[-1], reg_buf)))
Karsten Hopp 3c6980
  		    bow = FALSE;
Karsten Hopp 3c6980
  		if (bow)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  	    }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
--- 4277,4284 ----
Karsten Hopp 3c6980
  				   && vim_iswordc_buf(reginput[-1], reg_buf)))
Karsten Hopp 3c6980
  		    bow = FALSE;
Karsten Hopp 3c6980
  		if (bow)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  	    }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4176,4194 ****
Karsten Hopp 3c6980
  					   && vim_iswordc_buf(curc, reg_buf)))
Karsten Hopp 3c6980
  		    eow = FALSE;
Karsten Hopp 3c6980
  		if (eow)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  	    }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_BOF:
Karsten Hopp 3c6980
  		if (reglnum == 0 && reginput == regline
Karsten Hopp 3c6980
  					&& (!REG_MULTI || reg_firstlnum == 1))
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_EOF:
Karsten Hopp 3c6980
  		if (reglnum == reg_maxline && curc == NUL)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  #ifdef FEAT_MBYTE
Karsten Hopp 3c6980
--- 4306,4327 ----
Karsten Hopp 3c6980
  					   && vim_iswordc_buf(curc, reg_buf)))
Karsten Hopp 3c6980
  		    eow = FALSE;
Karsten Hopp 3c6980
  		if (eow)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  	    }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_BOF:
Karsten Hopp 3c6980
  		if (reglnum == 0 && reginput == regline
Karsten Hopp 3c6980
  					&& (!REG_MULTI || reg_firstlnum == 1))
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_EOF:
Karsten Hopp 3c6980
  		if (reglnum == reg_maxline && curc == NUL)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  #ifdef FEAT_MBYTE
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4277,4288 ****
Karsten Hopp 3c6980
  		    go_to_nextline = TRUE;
Karsten Hopp 3c6980
  		    /* Pass -1 for the offset, which means taking the position
Karsten Hopp 3c6980
  		     * at the start of the next line. */
Karsten Hopp 3c6980
! 		    addstate(nextlist, t->state->out, &t->subs, -1);
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  		else if (curc == '\n' && reg_line_lbr)
Karsten Hopp 3c6980
  		{
Karsten Hopp 3c6980
  		    /* match \n as if it is an ordinary character */
Karsten Hopp 3c6980
! 		    addstate(nextlist, t->state->out, &t->subs, 1);
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
--- 4410,4425 ----
Karsten Hopp 3c6980
  		    go_to_nextline = TRUE;
Karsten Hopp 3c6980
  		    /* Pass -1 for the offset, which means taking the position
Karsten Hopp 3c6980
  		     * at the start of the next line. */
Karsten Hopp 3c6980
! 		    ll = nextlist;
Karsten Hopp 3c6980
! 		    add_state = t->state->out;
Karsten Hopp 3c6980
! 		    add_off = -1;
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  		else if (curc == '\n' && reg_line_lbr)
Karsten Hopp 3c6980
  		{
Karsten Hopp 3c6980
  		    /* match \n as if it is an ordinary character */
Karsten Hopp 3c6980
! 		    ll = nextlist;
Karsten Hopp 3c6980
! 		    add_state = t->state->out;
Karsten Hopp 3c6980
! 		    add_off = 1;
Karsten Hopp 3c6980
  		}
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4310,4322 ****
Karsten Hopp 3c6980
  		/* This follows a series of negated nodes, like:
Karsten Hopp 3c6980
  		 * CHAR(x), NFA_NOT, CHAR(y), NFA_NOT etc. */
Karsten Hopp 3c6980
  		if (curc > 0)
Karsten Hopp 3c6980
! 		    addstate(nextlist, t->state->out, &t->subs, clen);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_ANY:
Karsten Hopp 3c6980
  		/* Any char except '\0', (end of input) does not match. */
Karsten Hopp 3c6980
  		if (curc > 0)
Karsten Hopp 3c6980
! 		    addstate(nextlist, t->state->out, &t->subs, clen);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    /*
Karsten Hopp 3c6980
--- 4447,4467 ----
Karsten Hopp 3c6980
  		/* This follows a series of negated nodes, like:
Karsten Hopp 3c6980
  		 * CHAR(x), NFA_NOT, CHAR(y), NFA_NOT etc. */
Karsten Hopp 3c6980
  		if (curc > 0)
Karsten Hopp 3c6980
! 		{
Karsten Hopp 3c6980
! 		    ll = nextlist;
Karsten Hopp 3c6980
! 		    add_state = t->state->out;
Karsten Hopp 3c6980
! 		    add_off = clen;
Karsten Hopp 3c6980
! 		}
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_ANY:
Karsten Hopp 3c6980
  		/* Any char except '\0', (end of input) does not match. */
Karsten Hopp 3c6980
  		if (curc > 0)
Karsten Hopp 3c6980
! 		{
Karsten Hopp 3c6980
! 		    ll = nextlist;
Karsten Hopp 3c6980
! 		    add_state = t->state->out;
Karsten Hopp 3c6980
! 		    add_off = clen;
Karsten Hopp 3c6980
! 		}
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    /*
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4498,4510 ****
Karsten Hopp 3c6980
  			/* empty match always works, output of NFA_SKIP to be
Karsten Hopp 3c6980
  			 * used next */
Karsten Hopp 3c6980
  			addstate_here(thislist, t->state->out->out, &t->subs,
Karsten Hopp 3c6980
! 								    &listidx);
Karsten Hopp 3c6980
  		    }
Karsten Hopp 3c6980
  		    else if (bytelen <= clen)
Karsten Hopp 3c6980
  		    {
Karsten Hopp 3c6980
  			/* match current character, jump ahead to out of
Karsten Hopp 3c6980
  			 * NFA_SKIP */
Karsten Hopp 3c6980
! 			addstate(nextlist, t->state->out->out, &t->subs, clen);
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  			log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
--- 4643,4657 ----
Karsten Hopp 3c6980
  			/* empty match always works, output of NFA_SKIP to be
Karsten Hopp 3c6980
  			 * used next */
Karsten Hopp 3c6980
  			addstate_here(thislist, t->state->out->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		    }
Karsten Hopp 3c6980
  		    else if (bytelen <= clen)
Karsten Hopp 3c6980
  		    {
Karsten Hopp 3c6980
  			/* match current character, jump ahead to out of
Karsten Hopp 3c6980
  			 * NFA_SKIP */
Karsten Hopp 3c6980
! 			ll = nextlist;
Karsten Hopp 3c6980
! 			add_state = t->state->out->out;
Karsten Hopp 3c6980
! 			add_off = clen;
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  			log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4513,4520 ****
Karsten Hopp 3c6980
  		    {
Karsten Hopp 3c6980
  			/* skip ofer the matched characters, set character
Karsten Hopp 3c6980
  			 * count in NFA_SKIP */
Karsten Hopp 3c6980
! 			addstate(nextlist, t->state->out, &t->subs, bytelen);
Karsten Hopp 3c6980
! 			nextlist->t[nextlist->n - 1].count = bytelen - clen;
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  			log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
--- 4660,4669 ----
Karsten Hopp 3c6980
  		    {
Karsten Hopp 3c6980
  			/* skip ofer the matched characters, set character
Karsten Hopp 3c6980
  			 * count in NFA_SKIP */
Karsten Hopp 3c6980
! 			ll = nextlist;
Karsten Hopp 3c6980
! 			add_state = t->state->out;
Karsten Hopp 3c6980
! 			add_off = bytelen;
Karsten Hopp 3c6980
! 			add_count = bytelen - clen;
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  			log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4528,4534 ****
Karsten Hopp 3c6980
  	      if (t->count - clen <= 0)
Karsten Hopp 3c6980
  	      {
Karsten Hopp 3c6980
  		  /* end of match, go to what follows */
Karsten Hopp 3c6980
! 		  addstate(nextlist, t->state->out, &t->subs, clen);
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  		  log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
--- 4677,4685 ----
Karsten Hopp 3c6980
  	      if (t->count - clen <= 0)
Karsten Hopp 3c6980
  	      {
Karsten Hopp 3c6980
  		  /* end of match, go to what follows */
Karsten Hopp 3c6980
! 		  ll = nextlist;
Karsten Hopp 3c6980
! 		  add_state = t->state->out;
Karsten Hopp 3c6980
! 		  add_off = clen;
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  		  log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4536,4543 ****
Karsten Hopp 3c6980
  	      else
Karsten Hopp 3c6980
  	      {
Karsten Hopp 3c6980
  		  /* add state again with decremented count */
Karsten Hopp 3c6980
! 		  addstate(nextlist, t->state, &t->subs, 0);
Karsten Hopp 3c6980
! 		  nextlist->t[nextlist->n - 1].count = t->count - clen;
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  		  log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
--- 4687,4696 ----
Karsten Hopp 3c6980
  	      else
Karsten Hopp 3c6980
  	      {
Karsten Hopp 3c6980
  		  /* add state again with decremented count */
Karsten Hopp 3c6980
! 		  ll = nextlist;
Karsten Hopp 3c6980
! 		  add_state = t->state;
Karsten Hopp 3c6980
! 		  add_off = 0;
Karsten Hopp 3c6980
! 		  add_count = t->count - clen;
Karsten Hopp 3c6980
  #ifdef ENABLE_LOG
Karsten Hopp 3c6980
  		  log_subsexpr(&nextlist->t[nextlist->n - 1].subs);
Karsten Hopp 3c6980
  #endif
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4557,4563 ****
Karsten Hopp 3c6980
  			nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM,
Karsten Hopp 3c6980
  			    (long_u)(reglnum + reg_firstlnum)));
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_COL:
Karsten Hopp 3c6980
--- 4710,4717 ----
Karsten Hopp 3c6980
  			nfa_re_num_cmp(t->state->val, t->state->c - NFA_LNUM,
Karsten Hopp 3c6980
  			    (long_u)(reglnum + reg_firstlnum)));
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_COL:
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4566,4572 ****
Karsten Hopp 3c6980
  		result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_COL,
Karsten Hopp 3c6980
  			(long_u)(reginput - regline) + 1);
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_VCOL:
Karsten Hopp 3c6980
--- 4720,4727 ----
Karsten Hopp 3c6980
  		result = nfa_re_num_cmp(t->state->val, t->state->c - NFA_COL,
Karsten Hopp 3c6980
  			(long_u)(reginput - regline) + 1);
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_VCOL:
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4577,4583 ****
Karsten Hopp 3c6980
  			    reg_win == NULL ? curwin : reg_win,
Karsten Hopp 3c6980
  			    regline, (colnr_T)(reginput - regline)) + 1);
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_CURSOR:
Karsten Hopp 3c6980
--- 4732,4739 ----
Karsten Hopp 3c6980
  			    reg_win == NULL ? curwin : reg_win,
Karsten Hopp 3c6980
  			    regline, (colnr_T)(reginput - regline)) + 1);
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    case NFA_CURSOR:
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4586,4592 ****
Karsten Hopp 3c6980
  			&& ((colnr_T)(reginput - regline)
Karsten Hopp 3c6980
  						   == reg_win->w_cursor.col));
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    default:	/* regular character */
Karsten Hopp 3c6980
--- 4742,4749 ----
Karsten Hopp 3c6980
  			&& ((colnr_T)(reginput - regline)
Karsten Hopp 3c6980
  						   == reg_win->w_cursor.col));
Karsten Hopp 3c6980
  		if (result)
Karsten Hopp 3c6980
! 		    addstate_here(thislist, t->state->out, &t->subs,
Karsten Hopp 3c6980
! 							    t->pim, &listidx);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	    default:	/* regular character */
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4613,4618 ****
Karsten Hopp 3c6980
--- 4770,4834 ----
Karsten Hopp 3c6980
  		ADD_POS_NEG_STATE(t->state);
Karsten Hopp 3c6980
  		break;
Karsten Hopp 3c6980
  	      }
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+ 	    } /* switch (t->state->c) */
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+ 	    if (add_state != NULL)
Karsten Hopp 3c6980
+ 	    {
Karsten Hopp 3c6980
+ 		if (t->pim != NULL)
Karsten Hopp 3c6980
+ 		{
Karsten Hopp 3c6980
+ 		    /* postponed invisible match */
Karsten Hopp 3c6980
+ 		    /* TODO: also do t->pim->pim recursively? */
Karsten Hopp 3c6980
+ 		    if (t->pim->result == NFA_PIM_TODO)
Karsten Hopp 3c6980
+ 		    {
Karsten Hopp 3c6980
+ #ifdef ENABLE_LOG
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "\n");
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "==================================\n");
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "Postponed recursive nfa_regmatch()\n");
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "\n");
Karsten Hopp 3c6980
+ #endif
Karsten Hopp 3c6980
+ 			result = recursive_regmatch(t->pim->state,
Karsten Hopp 3c6980
+ 						 prog, submatch, m, &listids);
Karsten Hopp 3c6980
+ 			t->pim->result = result ? NFA_PIM_MATCH
Karsten Hopp 3c6980
+ 							    : NFA_PIM_NOMATCH;
Karsten Hopp 3c6980
+ 			/* for \@! it is a match when result is FALSE */
Karsten Hopp 3c6980
+ 			if (result != t->pim->state->negated)
Karsten Hopp 3c6980
+ 			{
Karsten Hopp 3c6980
+ 			    /* Copy submatch info from the recursive call */
Karsten Hopp 3c6980
+ 			    copy_sub_off(&t->pim->subs.norm, &m->norm);
Karsten Hopp 3c6980
+ #ifdef FEAT_SYN_HL
Karsten Hopp 3c6980
+ 			    copy_sub_off(&t->pim->subs.synt, &m->synt);
Karsten Hopp 3c6980
+ #endif
Karsten Hopp 3c6980
+ 			}
Karsten Hopp 3c6980
+ 		    }
Karsten Hopp 3c6980
+ 		    else
Karsten Hopp 3c6980
+ 		    {
Karsten Hopp 3c6980
+ 			result = (t->pim->result == NFA_PIM_MATCH);
Karsten Hopp 3c6980
+ #ifdef ENABLE_LOG
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "\n");
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "Using previous recursive nfa_regmatch() result, result == %d\n", t->pim->result);
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
Karsten Hopp 3c6980
+ 			fprintf(log_fd, "\n");
Karsten Hopp 3c6980
+ #endif
Karsten Hopp 3c6980
+ 		    }
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+ 		    /* for \@! it is a match when result is FALSE */
Karsten Hopp 3c6980
+ 		    if (result != t->pim->state->negated)
Karsten Hopp 3c6980
+ 		    {
Karsten Hopp 3c6980
+ 			/* Copy submatch info from the recursive call */
Karsten Hopp 3c6980
+ 			copy_sub_off(&t->subs.norm, &t->pim->subs.norm);
Karsten Hopp 3c6980
+ #ifdef FEAT_SYN_HL
Karsten Hopp 3c6980
+ 			copy_sub_off(&t->subs.synt, &t->pim->subs.synt);
Karsten Hopp 3c6980
+ #endif
Karsten Hopp 3c6980
+ 		    }
Karsten Hopp 3c6980
+ 		    else
Karsten Hopp 3c6980
+ 			/* look-behind match failed, don't add the state */
Karsten Hopp 3c6980
+ 			continue;
Karsten Hopp 3c6980
+ 		}
Karsten Hopp 3c6980
+ 
Karsten Hopp 3c6980
+ 		addstate(ll, add_state, &t->subs, add_off);
Karsten Hopp 3c6980
+ 		if (add_count > 0)
Karsten Hopp 3c6980
+ 		    nextlist->t[ll->n - 1].count = add_count;
Karsten Hopp 3c6980
  	    }
Karsten Hopp 3c6980
  
Karsten Hopp 3c6980
  	} /* for (thislist = thislist; thislist->state; thislist++) */
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 4680,4685 ****
Karsten Hopp 3c6980
--- 4896,4902 ----
Karsten Hopp 3c6980
      vim_free(list[1].t);
Karsten Hopp 3c6980
      vim_free(list[2].t);
Karsten Hopp 3c6980
      vim_free(listids);
Karsten Hopp 3c6980
+     ga_clear(&pimlist);
Karsten Hopp 3c6980
  #undef ADD_POS_NEG_STATE
Karsten Hopp 3c6980
  #ifdef NFA_REGEXP_DEBUG_LOG
Karsten Hopp 3c6980
      fclose(debug);
Karsten Hopp 3c6980
*** ../vim-7.3.1109/src/version.c	2013-06-03 20:12:47.000000000 +0200
Karsten Hopp 3c6980
--- src/version.c	2013-06-04 13:51:17.000000000 +0200
Karsten Hopp 3c6980
***************
Karsten Hopp 3c6980
*** 730,731 ****
Karsten Hopp 3c6980
--- 730,733 ----
Karsten Hopp 3c6980
  {   /* Add new patch number below this line */
Karsten Hopp 3c6980
+ /**/
Karsten Hopp 3c6980
+     1110,
Karsten Hopp 3c6980
  /**/
Karsten Hopp 3c6980
Karsten Hopp 3c6980
-- 
Karsten Hopp 3c6980
hundred-and-one symptoms of being an internet addict:
Karsten Hopp 3c6980
80. At parties, you introduce your spouse as your "service provider."
Karsten Hopp 3c6980
Karsten Hopp 3c6980
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp 3c6980
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp 3c6980
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp 3c6980
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///