Patch 7.1.292
Problem:    When using a pattern with "\@<=" the submatches can be wrong.
            (Brett Stahlman)
Solution:   Save the submatches when attempting a look-behind match.
Files:      src/regexp.c


*** ../vim-7.1.291/src/regexp.c Sat Jan 19 15:55:51 2008
--- src/regexp.c        Tue Apr  1 18:15:47 2008
***************
*** 3039,3044 ****
--- 3039,3053 ----
      } se_u;
  } save_se_T;
  
+ /* used for BEHIND and NOBEHIND matching */
+ typedef struct regbehind_S
+ {
+     regsave_T save_after;
+     regsave_T save_behind;
+     save_se_T   save_start[NSUBEXP];
+     save_se_T   save_end[NSUBEXP];
+ } regbehind_T;
+ 
  static char_u *reg_getline __ARGS((linenr_T lnum));
  static long   vim_regexec_both __ARGS((char_u *line, colnr_T col, proftime_T 
*tm));
  static long   regtry __ARGS((regprog_T *prog, colnr_T col));
***************
*** 3046,3051 ****
--- 3055,3062 ----
  #ifdef FEAT_SYN_HL
  static void   cleanup_zsubexpr __ARGS((void));
  #endif
+ static void   save_subexpr __ARGS((regbehind_T *bp));
+ static void   restore_subexpr __ARGS((regbehind_T *bp));
  static void   reg_nextline __ARGS((void));
  static void   reg_save __ARGS((regsave_T *save, garray_T *gap));
  static void   reg_restore __ARGS((regsave_T *save, garray_T *gap));
***************
*** 3166,3184 ****
        save_se_T  sesave;
        regsave_T  regsave;
      } rs_un;                  /* room for saving reginput */
!     short     rs_no;          /* submatch nr */
  } regitem_T;
  
  static regitem_T *regstack_push __ARGS((regstate_T state, char_u *scan));
  static void regstack_pop __ARGS((char_u **scan));
  
- /* used for BEHIND and NOBEHIND matching */
- typedef struct regbehind_S
- {
-     regsave_T save_after;
-     regsave_T save_behind;
- } regbehind_T;
- 
  /* used for STAR, PLUS and BRACE_SIMPLE matching */
  typedef struct regstar_S
  {
--- 3177,3188 ----
        save_se_T  sesave;
        regsave_T  regsave;
      } rs_un;                  /* room for saving reginput */
!     short     rs_no;          /* submatch nr or BEHIND/NOBEHIND */
  } regitem_T;
  
  static regitem_T *regstack_push __ARGS((regstate_T state, char_u *scan));
  static void regstack_pop __ARGS((char_u **scan));
  
  /* used for STAR, PLUS and BRACE_SIMPLE matching */
  typedef struct regstar_S
  {
***************
*** 4888,4893 ****
--- 4892,4901 ----
                    status = RA_FAIL;
                else
                {
+                   /* Need to save the subexpr to be able to restore them
+                    * when there is a match but we don't use it. */
+                   save_subexpr(((regbehind_T *)rp) - 1);
+ 
                    rp->rs_no = op;
                    reg_save(&rp->rs_un.regsave, &backpos);
                    /* First try if what follows matches.  If it does then we
***************
*** 5118,5132 ****
                    reg_restore(&(((regbehind_T *)rp) - 1)->save_after,
                                                                    &backpos);
                else
!                   /* But we didn't want a match. */
                    status = RA_NOMATCH;
                regstack_pop(&scan);
                regstack.ga_len -= sizeof(regbehind_T);
            }
            else
            {
!               /* No match: Go back one character.  May go to previous
!                * line once. */
                no = OK;
                if (REG_MULTI)
                {
--- 5126,5145 ----
                    reg_restore(&(((regbehind_T *)rp) - 1)->save_after,
                                                                    &backpos);
                else
!               {
!                   /* But we didn't want a match.  Need to restore the
!                    * subexpr, because what follows matched, so they have
!                    * been set. */
                    status = RA_NOMATCH;
+                   restore_subexpr(((regbehind_T *)rp) - 1);
+               }
                regstack_pop(&scan);
                regstack.ga_len -= sizeof(regbehind_T);
            }
            else
            {
!               /* No match or a match that doesn't end where we want it: Go
!                * back one character.  May go to previous line once. */
                no = OK;
                if (REG_MULTI)
                {
***************
*** 5160,5165 ****
--- 5173,5185 ----
                    /* Advanced, prepare for finding match again. */
                    reg_restore(&rp->rs_un.regsave, &backpos);
                    scan = OPERAND(rp->rs_scan);
+                   if (status == RA_MATCH)
+                   {
+                       /* We did match, so subexpr may have been changed,
+                        * need to restore them for the next try. */
+                       status = RA_NOMATCH;
+                       restore_subexpr(((regbehind_T *)rp) - 1);
+                   }
                }
                else
                {
***************
*** 5172,5178 ****
                        status = RA_MATCH;
                    }
                    else
!                       status = RA_NOMATCH;
                    regstack_pop(&scan);
                    regstack.ga_len -= sizeof(regbehind_T);
                }
--- 5192,5207 ----
                        status = RA_MATCH;
                    }
                    else
!                   {
!                       /* We do want a proper match.  Need to restore the
!                        * subexpr if we had a match, because they may have
!                        * been set. */
!                       if (status == RA_MATCH)
!                       {
!                           status = RA_NOMATCH;
!                           restore_subexpr(((regbehind_T *)rp) - 1);
!                       }
!                   }
                    regstack_pop(&scan);
                    regstack.ga_len -= sizeof(regbehind_T);
                }
***************
*** 5820,5825 ****
--- 5849,5903 ----
  #endif
  
  /*
+  * Save the current subexpr to "bp", so that they can be restored
+  * later by restore_subexpr().
+  */
+     static void
+ save_subexpr(bp)
+     regbehind_T *bp;
+ {
+     int i;
+ 
+     for (i = 0; i < NSUBEXP; ++i)
+     {
+       if (REG_MULTI)
+       {
+           bp->save_start[i].se_u.pos = reg_startpos[i];
+           bp->save_end[i].se_u.pos = reg_endpos[i];
+       }
+       else
+       {
+           bp->save_start[i].se_u.ptr = reg_startp[i];
+           bp->save_end[i].se_u.ptr = reg_endp[i];
+       }
+     }
+ }
+ 
+ /*
+  * Restore the subexpr from "bp".
+  */
+     static void
+ restore_subexpr(bp)
+     regbehind_T *bp;
+ {
+     int i;
+ 
+     for (i = 0; i < NSUBEXP; ++i)
+     {
+       if (REG_MULTI)
+       {
+           reg_startpos[i] = bp->save_start[i].se_u.pos;
+           reg_endpos[i] = bp->save_end[i].se_u.pos;
+       }
+       else
+       {
+           reg_startp[i] = bp->save_start[i].se_u.ptr;
+           reg_endp[i] = bp->save_end[i].se_u.ptr;
+       }
+     }
+ }
+ 
+ /*
   * Advance reglnum, regline and reginput to the next line.
   */
      static void
*** ../vim-7.1.291/src/version.c        Tue Apr  1 20:58:23 2008
--- src/version.c       Wed Apr  9 12:12:33 2008
***************
*** 668,669 ****
--- 673,676 ----
  {   /* Add new patch number below this line */
+ /**/
+     292,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
259. When you enter your name in the AltaVista search engine, the top ten
     matches do indeed refer to you.

 /// Bram Moolenaar -- [EMAIL PROTECTED] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Raspunde prin e-mail lui