To: vim-dev@vim.org Subject: Patch 7.1.292 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@Moolenaar.net -- 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 ///