Karsten Hopp 13d265
To: vim_dev@googlegroups.com
Karsten Hopp 13d265
Subject: Patch 7.3.1071
Karsten Hopp 13d265
Fcc: outbox
Karsten Hopp 13d265
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp 13d265
Mime-Version: 1.0
Karsten Hopp 13d265
Content-Type: text/plain; charset=UTF-8
Karsten Hopp 13d265
Content-Transfer-Encoding: 8bit
Karsten Hopp 13d265
------------
Karsten Hopp 13d265
Karsten Hopp 13d265
Patch 7.3.1071
Karsten Hopp 13d265
Problem:    New regexp engine: backreferences don't work correctly.
Karsten Hopp 13d265
Solution:   Add every possible start/end position on the state stack.
Karsten Hopp 13d265
Files:	    src/regexp_nfa.c, src/regexp.h, src/testdir/test64.in,
Karsten Hopp 13d265
	    src/testdir/test64.ok
Karsten Hopp 13d265
Karsten Hopp 13d265
Karsten Hopp 13d265
*** ../vim-7.3.1070/src/regexp_nfa.c	2013-05-30 11:51:04.000000000 +0200
Karsten Hopp 13d265
--- src/regexp_nfa.c	2013-05-30 16:43:43.000000000 +0200
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 184,189 ****
Karsten Hopp 13d265
--- 184,192 ----
Karsten Hopp 13d265
  /* NFA regexp \ze operator encountered. */
Karsten Hopp 13d265
  static int nfa_has_zend;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
+ /* NFA regexp \1 .. \9 encountered. */
Karsten Hopp 13d265
+ static int nfa_has_backref;
Karsten Hopp 13d265
+ 
Karsten Hopp 13d265
  /* Number of sub expressions actually being used during execution. 1 if only
Karsten Hopp 13d265
   * the whole match (subexpr 0) is used. */
Karsten Hopp 13d265
  static int nfa_nsubexpr;
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 266,271 ****
Karsten Hopp 13d265
--- 269,275 ----
Karsten Hopp 13d265
      post_ptr = post_start;
Karsten Hopp 13d265
      post_end = post_start + nstate_max;
Karsten Hopp 13d265
      nfa_has_zend = FALSE;
Karsten Hopp 13d265
+     nfa_has_backref = FALSE;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
      regcomp_start(expr, re_flags);
Karsten Hopp 13d265
  
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 750,764 ****
Karsten Hopp 13d265
  	    /* TODO: Not supported yet */
Karsten Hopp 13d265
  	    return FAIL;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
! 	case Magic('1'): EMIT(NFA_BACKREF1); break;
Karsten Hopp 13d265
! 	case Magic('2'): EMIT(NFA_BACKREF2); break;
Karsten Hopp 13d265
! 	case Magic('3'): EMIT(NFA_BACKREF3); break;
Karsten Hopp 13d265
! 	case Magic('4'): EMIT(NFA_BACKREF4); break;
Karsten Hopp 13d265
! 	case Magic('5'): EMIT(NFA_BACKREF5); break;
Karsten Hopp 13d265
! 	case Magic('6'): EMIT(NFA_BACKREF6); break;
Karsten Hopp 13d265
! 	case Magic('7'): EMIT(NFA_BACKREF7); break;
Karsten Hopp 13d265
! 	case Magic('8'): EMIT(NFA_BACKREF8); break;
Karsten Hopp 13d265
! 	case Magic('9'): EMIT(NFA_BACKREF9); break;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
  	case Magic('z'):
Karsten Hopp 13d265
  	    c = no_Magic(getchr());
Karsten Hopp 13d265
--- 754,771 ----
Karsten Hopp 13d265
  	    /* TODO: Not supported yet */
Karsten Hopp 13d265
  	    return FAIL;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
! 	case Magic('1'):
Karsten Hopp 13d265
! 	case Magic('2'):
Karsten Hopp 13d265
! 	case Magic('3'):
Karsten Hopp 13d265
! 	case Magic('4'):
Karsten Hopp 13d265
! 	case Magic('5'):
Karsten Hopp 13d265
! 	case Magic('6'):
Karsten Hopp 13d265
! 	case Magic('7'):
Karsten Hopp 13d265
! 	case Magic('8'):
Karsten Hopp 13d265
! 	case Magic('9'):
Karsten Hopp 13d265
! 	    EMIT(NFA_BACKREF1 + (no_Magic(c) - '1'));
Karsten Hopp 13d265
! 	    nfa_has_backref = TRUE;
Karsten Hopp 13d265
! 	    break;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
  	case Magic('z'):
Karsten Hopp 13d265
  	    c = no_Magic(getchr());
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 2581,2587 ****
Karsten Hopp 13d265
  typedef struct
Karsten Hopp 13d265
  {
Karsten Hopp 13d265
      nfa_thread_T    *t;		/* allocated array of states */
Karsten Hopp 13d265
!     int		    n;		/* nr of states in "t" */
Karsten Hopp 13d265
      int		    id;		/* ID of the list */
Karsten Hopp 13d265
  } nfa_list_T;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
--- 2588,2595 ----
Karsten Hopp 13d265
  typedef struct
Karsten Hopp 13d265
  {
Karsten Hopp 13d265
      nfa_thread_T    *t;		/* allocated array of states */
Karsten Hopp 13d265
!     int		    n;		/* nr of states currently in "t" */
Karsten Hopp 13d265
!     int		    len;	/* max nr of states in "t" */
Karsten Hopp 13d265
      int		    id;		/* ID of the list */
Karsten Hopp 13d265
  } nfa_list_T;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 2612,2620 ****
Karsten Hopp 13d265
--- 2620,2711 ----
Karsten Hopp 13d265
  /* Used during execution: whether a match has been found. */
Karsten Hopp 13d265
  static int nfa_match;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
+ static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
Karsten Hopp 13d265
  static void addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsub_T *sub, int off));
Karsten Hopp 13d265
  static void addstate_here __ARGS((nfa_list_T *l, nfa_state_T *state, regsub_T *sub, int *ip));
Karsten Hopp 13d265
  
Karsten Hopp 13d265
+ /*
Karsten Hopp 13d265
+  * Return TRUE if "sub1" and "sub2" have the same positions.
Karsten Hopp 13d265
+  */
Karsten Hopp 13d265
+     static int
Karsten Hopp 13d265
+ sub_equal(sub1, sub2)
Karsten Hopp 13d265
+     regsub_T	*sub1;
Karsten Hopp 13d265
+     regsub_T	*sub2;
Karsten Hopp 13d265
+ {
Karsten Hopp 13d265
+     int		i;
Karsten Hopp 13d265
+     int		todo;
Karsten Hopp 13d265
+     linenr_T	s1, e1;
Karsten Hopp 13d265
+     linenr_T	s2, e2;
Karsten Hopp 13d265
+     char_u	*sp1, *ep1;
Karsten Hopp 13d265
+     char_u	*sp2, *ep2;
Karsten Hopp 13d265
+ 
Karsten Hopp 13d265
+     todo = sub1->in_use > sub2->in_use ? sub1->in_use : sub2->in_use;
Karsten Hopp 13d265
+     if (REG_MULTI)
Karsten Hopp 13d265
+     {
Karsten Hopp 13d265
+ 	for (i = 0; i < todo; ++i)
Karsten Hopp 13d265
+ 	{
Karsten Hopp 13d265
+ 	    if (i < sub1->in_use)
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		s1 = sub1->list.multi[i].start.lnum;
Karsten Hopp 13d265
+ 		e1 = sub1->list.multi[i].end.lnum;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    else
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		s1 = 0;
Karsten Hopp 13d265
+ 		e1 = 0;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    if (i < sub2->in_use)
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		s2 = sub2->list.multi[i].start.lnum;
Karsten Hopp 13d265
+ 		e2 = sub2->list.multi[i].end.lnum;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    else
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		s2 = 0;
Karsten Hopp 13d265
+ 		e2 = 0;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    if (s1 != s2 || e1 != e2)
Karsten Hopp 13d265
+ 		return FALSE;
Karsten Hopp 13d265
+ 	    if (s1 != 0 && sub1->list.multi[i].start.col
Karsten Hopp 13d265
+ 					     != sub2->list.multi[i].start.col)
Karsten Hopp 13d265
+ 		return FALSE;
Karsten Hopp 13d265
+ 	    if (e1 != 0 && sub1->list.multi[i].end.col
Karsten Hopp 13d265
+ 					     != sub2->list.multi[i].end.col)
Karsten Hopp 13d265
+ 		return FALSE;
Karsten Hopp 13d265
+ 	}
Karsten Hopp 13d265
+     }
Karsten Hopp 13d265
+     else
Karsten Hopp 13d265
+     {
Karsten Hopp 13d265
+ 	for (i = 0; i < todo; ++i)
Karsten Hopp 13d265
+ 	{
Karsten Hopp 13d265
+ 	    if (i < sub1->in_use)
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		sp1 = sub1->list.line[i].start;
Karsten Hopp 13d265
+ 		ep1 = sub1->list.line[i].end;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    else
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		sp1 = NULL;
Karsten Hopp 13d265
+ 		ep1 = NULL;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    if (i < sub2->in_use)
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		sp2 = sub2->list.line[i].start;
Karsten Hopp 13d265
+ 		ep2 = sub2->list.line[i].end;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    else
Karsten Hopp 13d265
+ 	    {
Karsten Hopp 13d265
+ 		sp2 = NULL;
Karsten Hopp 13d265
+ 		ep2 = NULL;
Karsten Hopp 13d265
+ 	    }
Karsten Hopp 13d265
+ 	    if (sp1 != sp2 || ep1 != ep2)
Karsten Hopp 13d265
+ 		return FALSE;
Karsten Hopp 13d265
+ 	}
Karsten Hopp 13d265
+     }
Karsten Hopp 13d265
+ 
Karsten Hopp 13d265
+     return TRUE;
Karsten Hopp 13d265
+ }
Karsten Hopp 13d265
+ 
Karsten Hopp 13d265
      static void
Karsten Hopp 13d265
  addstate(l, state, sub, off)
Karsten Hopp 13d265
      nfa_list_T		*l;	/* runtime state list */
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 2623,2629 ****
Karsten Hopp 13d265
      int			off;	/* byte offset, when -1 go to next line */
Karsten Hopp 13d265
  {
Karsten Hopp 13d265
      int			subidx;
Karsten Hopp 13d265
!     nfa_thread_T	*lastthread;
Karsten Hopp 13d265
      lpos_T		save_lpos;
Karsten Hopp 13d265
      int			save_in_use;
Karsten Hopp 13d265
      char_u		*save_ptr;
Karsten Hopp 13d265
--- 2714,2720 ----
Karsten Hopp 13d265
      int			off;	/* byte offset, when -1 go to next line */
Karsten Hopp 13d265
  {
Karsten Hopp 13d265
      int			subidx;
Karsten Hopp 13d265
!     nfa_thread_T	*thread;
Karsten Hopp 13d265
      lpos_T		save_lpos;
Karsten Hopp 13d265
      int			save_in_use;
Karsten Hopp 13d265
      char_u		*save_ptr;
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 2674,2696 ****
Karsten Hopp 13d265
  	    {
Karsten Hopp 13d265
  		/* This state is already in the list, don't add it again,
Karsten Hopp 13d265
  		 * unless it is an MOPEN that is used for a backreference. */
Karsten Hopp 13d265
! 		return;
Karsten Hopp 13d265
  	    }
Karsten Hopp 13d265
  
Karsten Hopp 13d265
  	    /* add the state to the list */
Karsten Hopp 13d265
  	    state->lastlist = l->id;
Karsten Hopp 13d265
! 	    lastthread = &l->t[l->n++];
Karsten Hopp 13d265
! 	    lastthread->state = state;
Karsten Hopp 13d265
! 	    lastthread->sub.in_use = sub->in_use;
Karsten Hopp 13d265
  	    if (sub->in_use > 0)
Karsten Hopp 13d265
  	    {
Karsten Hopp 13d265
  		/* Copy the match start and end positions. */
Karsten Hopp 13d265
  		if (REG_MULTI)
Karsten Hopp 13d265
! 		    mch_memmove(&lastthread->sub.list.multi[0],
Karsten Hopp 13d265
  				&sub->list.multi[0],
Karsten Hopp 13d265
  				sizeof(struct multipos) * sub->in_use);
Karsten Hopp 13d265
  		else
Karsten Hopp 13d265
! 		    mch_memmove(&lastthread->sub.list.line[0],
Karsten Hopp 13d265
  				&sub->list.line[0],
Karsten Hopp 13d265
  				sizeof(struct linepos) * sub->in_use);
Karsten Hopp 13d265
  	    }
Karsten Hopp 13d265
--- 2765,2808 ----
Karsten Hopp 13d265
  	    {
Karsten Hopp 13d265
  		/* This state is already in the list, don't add it again,
Karsten Hopp 13d265
  		 * unless it is an MOPEN that is used for a backreference. */
Karsten Hopp 13d265
! 		if (!nfa_has_backref)
Karsten Hopp 13d265
! 		    return;
Karsten Hopp 13d265
! 
Karsten Hopp 13d265
! 		/* See if the same state is already in the list with the same
Karsten Hopp 13d265
! 		 * positions. */
Karsten Hopp 13d265
! 		for (i = 0; i < l->n; ++i)
Karsten Hopp 13d265
! 		{
Karsten Hopp 13d265
! 		    thread = &l->t[i];
Karsten Hopp 13d265
! 		    if (thread->state->id == state->id
Karsten Hopp 13d265
! 					  && sub_equal(&thread->sub, sub))
Karsten Hopp 13d265
! 			return;
Karsten Hopp 13d265
! 		}
Karsten Hopp 13d265
! 	    }
Karsten Hopp 13d265
! 
Karsten Hopp 13d265
! 	    /* when there are backreferences the number of states may be (a
Karsten Hopp 13d265
! 	     * lot) bigger */
Karsten Hopp 13d265
! 	    if (nfa_has_backref && l->n == l->len)
Karsten Hopp 13d265
! 	    {
Karsten Hopp 13d265
! 		int newlen = l->len * 3 / 2 + 50;
Karsten Hopp 13d265
! 
Karsten Hopp 13d265
! 		l->t = vim_realloc(l->t, newlen * sizeof(nfa_thread_T));
Karsten Hopp 13d265
! 		l->len = newlen;
Karsten Hopp 13d265
  	    }
Karsten Hopp 13d265
  
Karsten Hopp 13d265
  	    /* add the state to the list */
Karsten Hopp 13d265
  	    state->lastlist = l->id;
Karsten Hopp 13d265
! 	    thread = &l->t[l->n++];
Karsten Hopp 13d265
! 	    thread->state = state;
Karsten Hopp 13d265
! 	    thread->sub.in_use = sub->in_use;
Karsten Hopp 13d265
  	    if (sub->in_use > 0)
Karsten Hopp 13d265
  	    {
Karsten Hopp 13d265
  		/* Copy the match start and end positions. */
Karsten Hopp 13d265
  		if (REG_MULTI)
Karsten Hopp 13d265
! 		    mch_memmove(&thread->sub.list.multi[0],
Karsten Hopp 13d265
  				&sub->list.multi[0],
Karsten Hopp 13d265
  				sizeof(struct multipos) * sub->in_use);
Karsten Hopp 13d265
  		else
Karsten Hopp 13d265
! 		    mch_memmove(&thread->sub.list.line[0],
Karsten Hopp 13d265
  				&sub->list.line[0],
Karsten Hopp 13d265
  				sizeof(struct linepos) * sub->in_use);
Karsten Hopp 13d265
  	    }
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 2909,2915 ****
Karsten Hopp 13d265
  
Karsten Hopp 13d265
      /* re-order to put the new state at the current position */
Karsten Hopp 13d265
      count = l->n - tlen;
Karsten Hopp 13d265
!     if (count > 1)
Karsten Hopp 13d265
      {
Karsten Hopp 13d265
  	/* make space for new states, then move them from the
Karsten Hopp 13d265
  	 * end to the current position */
Karsten Hopp 13d265
--- 3021,3032 ----
Karsten Hopp 13d265
  
Karsten Hopp 13d265
      /* re-order to put the new state at the current position */
Karsten Hopp 13d265
      count = l->n - tlen;
Karsten Hopp 13d265
!     if (count == 1)
Karsten Hopp 13d265
!     {
Karsten Hopp 13d265
! 	/* overwrite the current state */
Karsten Hopp 13d265
! 	l->t[i] = l->t[l->n - 1];
Karsten Hopp 13d265
!     }
Karsten Hopp 13d265
!     else if (count > 1)
Karsten Hopp 13d265
      {
Karsten Hopp 13d265
  	/* make space for new states, then move them from the
Karsten Hopp 13d265
  	 * end to the current position */
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 2920,2930 ****
Karsten Hopp 13d265
  		&(l->t[l->n - 1]),
Karsten Hopp 13d265
  		sizeof(nfa_thread_T) * count);
Karsten Hopp 13d265
      }
Karsten Hopp 13d265
-     else
Karsten Hopp 13d265
-     {
Karsten Hopp 13d265
- 	/* overwrite the current state */
Karsten Hopp 13d265
- 	l->t[i] = l->t[l->n - 1];
Karsten Hopp 13d265
-     }
Karsten Hopp 13d265
      --l->n;
Karsten Hopp 13d265
      *ip = i - 1;
Karsten Hopp 13d265
  }
Karsten Hopp 13d265
--- 3037,3042 ----
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 3183,3196 ****
Karsten Hopp 13d265
  
Karsten Hopp 13d265
      /* Allocate memory for the lists of nodes. */
Karsten Hopp 13d265
      size = (nstate + 1) * sizeof(nfa_thread_T);
Karsten Hopp 13d265
!     list[0].t = (nfa_thread_T *)lalloc(size, TRUE);
Karsten Hopp 13d265
!     list[1].t = (nfa_thread_T *)lalloc(size, TRUE);
Karsten Hopp 13d265
!     list[2].t = (nfa_thread_T *)lalloc(size, TRUE);
Karsten Hopp 13d265
      if (list[0].t == NULL || list[1].t == NULL || list[2].t == NULL)
Karsten Hopp 13d265
  	goto theend;
Karsten Hopp 13d265
-     vim_memset(list[0].t, 0, size);
Karsten Hopp 13d265
-     vim_memset(list[1].t, 0, size);
Karsten Hopp 13d265
-     vim_memset(list[2].t, 0, size);
Karsten Hopp 13d265
  
Karsten Hopp 13d265
  #ifdef ENABLE_LOG
Karsten Hopp 13d265
      log_fd = fopen(NFA_REGEXP_RUN_LOG, "a");
Karsten Hopp 13d265
--- 3295,3308 ----
Karsten Hopp 13d265
  
Karsten Hopp 13d265
      /* Allocate memory for the lists of nodes. */
Karsten Hopp 13d265
      size = (nstate + 1) * sizeof(nfa_thread_T);
Karsten Hopp 13d265
!     list[0].t = (nfa_thread_T *)lalloc_clear(size, TRUE);
Karsten Hopp 13d265
!     list[0].len = nstate + 1;
Karsten Hopp 13d265
!     list[1].t = (nfa_thread_T *)lalloc_clear(size, TRUE);
Karsten Hopp 13d265
!     list[1].len = nstate + 1;
Karsten Hopp 13d265
!     list[2].t = (nfa_thread_T *)lalloc_clear(size, TRUE);
Karsten Hopp 13d265
!     list[2].len = nstate + 1;
Karsten Hopp 13d265
      if (list[0].t == NULL || list[1].t == NULL || list[2].t == NULL)
Karsten Hopp 13d265
  	goto theend;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
  #ifdef ENABLE_LOG
Karsten Hopp 13d265
      log_fd = fopen(NFA_REGEXP_RUN_LOG, "a");
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 3970,3976 ****
Karsten Hopp 13d265
      vim_free(list[0].t);
Karsten Hopp 13d265
      vim_free(list[1].t);
Karsten Hopp 13d265
      vim_free(list[2].t);
Karsten Hopp 13d265
-     list[0].t = list[1].t = list[2].t = NULL;
Karsten Hopp 13d265
      vim_free(listids);
Karsten Hopp 13d265
  #undef ADD_POS_NEG_STATE
Karsten Hopp 13d265
  #ifdef NFA_REGEXP_DEBUG_LOG
Karsten Hopp 13d265
--- 4082,4087 ----
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 4131,4136 ****
Karsten Hopp 13d265
--- 4242,4248 ----
Karsten Hopp 13d265
      reglnum = 0;    /* relative to line */
Karsten Hopp 13d265
  
Karsten Hopp 13d265
      nfa_has_zend = prog->has_zend;
Karsten Hopp 13d265
+     nfa_has_backref = prog->has_backref;
Karsten Hopp 13d265
      nfa_nsubexpr = prog->nsubexp;
Karsten Hopp 13d265
  
Karsten Hopp 13d265
      nstate = prog->nstate;
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 4225,4230 ****
Karsten Hopp 13d265
--- 4337,4343 ----
Karsten Hopp 13d265
      prog->engine = &nfa_regengine;
Karsten Hopp 13d265
      prog->nstate = nstate;
Karsten Hopp 13d265
      prog->has_zend = nfa_has_zend;
Karsten Hopp 13d265
+     prog->has_backref = nfa_has_backref;
Karsten Hopp 13d265
      prog->nsubexp = regnpar;
Karsten Hopp 13d265
  #ifdef ENABLE_LOG
Karsten Hopp 13d265
      nfa_postfix_dump(expr, OK);
Karsten Hopp 13d265
*** ../vim-7.3.1070/src/regexp.h	2013-05-29 21:14:37.000000000 +0200
Karsten Hopp 13d265
--- src/regexp.h	2013-05-30 15:54:53.000000000 +0200
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 87,92 ****
Karsten Hopp 13d265
--- 87,93 ----
Karsten Hopp 13d265
      regprog_T		regprog;
Karsten Hopp 13d265
      nfa_state_T		*start;
Karsten Hopp 13d265
      int			has_zend;	/* pattern contains \ze */
Karsten Hopp 13d265
+     int			has_backref;	/* pattern contains \1 .. \9 */
Karsten Hopp 13d265
      int			nsubexp;	/* number of () */
Karsten Hopp 13d265
      int			nstate;
Karsten Hopp 13d265
      nfa_state_T		state[0];	/* actually longer.. */
Karsten Hopp 13d265
*** ../vim-7.3.1070/src/testdir/test64.in	2013-05-30 11:51:04.000000000 +0200
Karsten Hopp 13d265
--- src/testdir/test64.in	2013-05-30 16:47:29.000000000 +0200
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 333,339 ****
Karsten Hopp 13d265
  :"
Karsten Hopp 13d265
  :"""" Back references
Karsten Hopp 13d265
  :call add(tl, [2, '\(\i\+\) \1', ' abc abc', 'abc abc', 'abc'])
Karsten Hopp 13d265
! :"call add(tl, [2, '\(\i\+\) \1', 'xgoo goox', 'goo goo', 'goo'])
Karsten Hopp 13d265
  :call add(tl, [2, '\(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9', 'xabcddefghiabcddefghix', 'abcddefghiabcddefghi', 'a', 'b', 'c', 'dd', 'e', 'f', 'g', 'h', 'i'])
Karsten Hopp 13d265
  :"
Karsten Hopp 13d265
  :"""" Look-behind with limit
Karsten Hopp 13d265
--- 333,339 ----
Karsten Hopp 13d265
  :"
Karsten Hopp 13d265
  :"""" Back references
Karsten Hopp 13d265
  :call add(tl, [2, '\(\i\+\) \1', ' abc abc', 'abc abc', 'abc'])
Karsten Hopp 13d265
! :call add(tl, [2, '\(\i\+\) \1', 'xgoo goox', 'goo goo', 'goo'])
Karsten Hopp 13d265
  :call add(tl, [2, '\(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9', 'xabcddefghiabcddefghix', 'abcddefghiabcddefghi', 'a', 'b', 'c', 'dd', 'e', 'f', 'g', 'h', 'i'])
Karsten Hopp 13d265
  :"
Karsten Hopp 13d265
  :"""" Look-behind with limit
Karsten Hopp 13d265
*** ../vim-7.3.1070/src/testdir/test64.ok	2013-05-30 11:51:04.000000000 +0200
Karsten Hopp 13d265
--- src/testdir/test64.ok	2013-05-30 17:00:27.000000000 +0200
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 716,721 ****
Karsten Hopp 13d265
--- 716,724 ----
Karsten Hopp 13d265
  OK 0 - \(\i\+\) \1
Karsten Hopp 13d265
  OK 1 - \(\i\+\) \1
Karsten Hopp 13d265
  OK 2 - \(\i\+\) \1
Karsten Hopp 13d265
+ OK 0 - \(\i\+\) \1
Karsten Hopp 13d265
+ OK 1 - \(\i\+\) \1
Karsten Hopp 13d265
+ OK 2 - \(\i\+\) \1
Karsten Hopp 13d265
  OK 0 - \(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9
Karsten Hopp 13d265
  OK 1 - \(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9
Karsten Hopp 13d265
  OK 2 - \(a\)\(b\)\(c\)\(dd\)\(e\)\(f\)\(g\)\(h\)\(i\)\1\2\3\4\5\6\7\8\9
Karsten Hopp 13d265
*** ../vim-7.3.1070/src/version.c	2013-05-30 15:38:20.000000000 +0200
Karsten Hopp 13d265
--- src/version.c	2013-05-30 17:02:40.000000000 +0200
Karsten Hopp 13d265
***************
Karsten Hopp 13d265
*** 730,731 ****
Karsten Hopp 13d265
--- 730,733 ----
Karsten Hopp 13d265
  {   /* Add new patch number below this line */
Karsten Hopp 13d265
+ /**/
Karsten Hopp 13d265
+     1071,
Karsten Hopp 13d265
  /**/
Karsten Hopp 13d265
Karsten Hopp 13d265
-- 
Karsten Hopp 13d265
How To Keep A Healthy Level Of Insanity:
Karsten Hopp 13d265
14. Put mosquito netting around your work area. Play a tape of jungle
Karsten Hopp 13d265
    sounds all day.
Karsten Hopp 13d265
Karsten Hopp 13d265
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp 13d265
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp 13d265
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
Karsten Hopp 13d265
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///