To: [email protected]
Subject: Patch 7.4a.032
Fcc: outbox
From: Bram Moolenaar <[email protected]>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
------------

Patch 7.4a.032
Problem:    New regexp engine: Does not match shorter alternative. (Ingo
           Karkat)
Solution:   Do not drop a new state when the PIM info is different.
Files:      src/regexp_nfa.c


*** ../vim-7.4a.031/src/regexp_nfa.c    2013-07-17 19:22:04.000000000 +0200
--- src/regexp_nfa.c    2013-07-17 20:51:06.000000000 +0200
***************
*** 3535,3541 ****
 static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
 static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
 static int match_backref __ARGS((regsub_T *sub, int subidx, int *bytelen));
! static int has_state_with_pos __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
 static int state_in_list __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
 static regsubs_T *addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs_arg, 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));
--- 3535,3542 ----
 static void copy_sub_off __ARGS((regsub_T *to, regsub_T *from));
 static int sub_equal __ARGS((regsub_T *sub1, regsub_T *sub2));
 static int match_backref __ARGS((regsub_T *sub, int subidx, int *bytelen));
! static int has_state_with_pos __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim));
! static int pim_equal __ARGS((nfa_pim_T *one, nfa_pim_T *two));
 static int state_in_list __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs));
 static regsubs_T *addstate __ARGS((nfa_list_T *l, nfa_state_T *state, regsubs_T *subs_arg, 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));
***************
*** 3701,3710 ****
  * positions as "subs".
  */
     static int
! has_state_with_pos(l, state, subs)
     nfa_list_T                *l;     /* runtime state list */
     nfa_state_T               *state; /* state to update */
     regsubs_T         *subs;  /* pointers to subexpressions */
 {
     nfa_thread_T      *thread;
     int                       i;
--- 3702,3712 ----
  * positions as "subs".
  */
     static int
! has_state_with_pos(l, state, subs, pim)
     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 match or NULL */
 {
     nfa_thread_T      *thread;
     int                       i;
***************
*** 3718,3730 ****
               && (!nfa_has_zsubexpr
                               || sub_equal(&thread->subs.synt, &subs->synt))
 #endif
!                             )
           return TRUE;
     }
     return FALSE;
 }

 /*
  * Return TRUE if "state" leads to a NFA_MATCH without advancing the input.
  */
     static int
--- 3720,3757 ----
               && (!nfa_has_zsubexpr
                               || sub_equal(&thread->subs.synt, &subs->synt))
 #endif
!               && pim_equal(&thread->pim, pim))
           return TRUE;
     }
     return FALSE;
 }

 /*
+  * Return TRUE if "one" and "two" are equal.  That includes when both are not
+  * set.
+  */
+     static int
+ pim_equal(one, two)
+     nfa_pim_T *one;
+     nfa_pim_T *two;
+ {
+     int one_unused = (one == NULL || one->result == NFA_PIM_UNUSED);
+     int two_unused = (two == NULL || two->result == NFA_PIM_UNUSED);
+
+     if (one_unused)
+       /* one is unused: equal when two is also unused */
+       return two_unused;
+     if (two_unused)
+       /* one is used and two is not: not equal */
+       return FALSE;
+     /* compare the position */
+     if (REG_MULTI)
+       return one->end.pos.lnum == two->end.pos.lnum
+           && one->end.pos.col == two->end.pos.col;
+     return one->end.ptr == two->end.ptr;
+ }
+
+ /*
  * Return TRUE if "state" leads to a NFA_MATCH without advancing the input.
  */
     static int
***************
*** 3825,3831 ****
 {
     if (state->lastlist[nfa_ll_index] == l->id)
     {
!       if (!nfa_has_backref || has_state_with_pos(l, state, subs))
           return TRUE;
     }
     return FALSE;
--- 3852,3858 ----
 {
     if (state->lastlist[nfa_ll_index] == l->id)
     {
!       if (!nfa_has_backref || has_state_with_pos(l, state, subs, NULL))
           return TRUE;
     }
     return FALSE;
***************
*** 3952,3958 ****

               /* Do not add the state again when it exists with the same
                * positions. */
!               if (has_state_with_pos(l, state, subs))
                   goto skip_add;
           }

--- 3979,3985 ----

               /* Do not add the state again when it exists with the same
                * positions. */
!               if (has_state_with_pos(l, state, subs, pim))
                   goto skip_add;
           }

*** ../vim-7.4a.031/src/version.c       2013-07-17 19:22:04.000000000 +0200
--- src/version.c       2013-07-17 21:08:03.000000000 +0200
***************
*** 729,730 ****
--- 729,732 ----
 {   /* Add new patch number below this line */
+ /**/
+     32,
 /**/

--
It doesn't really matter what you are able to do if you don't do it.
                               (Bram Moolenaar)

/// Bram Moolenaar -- [email protected] -- 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    ///