| To: vim-dev@vim.org |
| Subject: Patch 7.1.292 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| 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 |
| |
| |
| |
| |
| |
| *** 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 |
| |
| |
| |
| *** 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 /// |