| To: vim_dev@googlegroups.com |
| Subject: Patch 7.3.1191 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.3.1191 |
| Problem: Backreference to previous line doesn't work. (Lech Lorens) |
| Solution: Implement looking in another line. |
| Files: src/regexp.c, src/regexp_nfa.c, src/testdir/test64.in, |
| src/testdir/test64.ok |
| |
| |
| |
| |
| |
| *** 3519,3524 **** |
| --- 3519,3525 ---- |
| *(pp) = (savep)->se_u.ptr; } |
| |
| static int re_num_cmp __ARGS((long_u val, char_u *scan)); |
| + static int match_with_backref __ARGS((linenr_T start_lnum, colnr_T start_col, linenr_T end_lnum, colnr_T end_col, int *bytelen)); |
| static int regmatch __ARGS((char_u *prog)); |
| static int regrepeat __ARGS((char_u *p, long maxcount)); |
| |
| |
| *** 4979,4987 **** |
| case BACKREF + 9: |
| { |
| int len; |
| - linenr_T clnum; |
| - colnr_T ccol; |
| - char_u *p; |
| |
| no = op - BACKREF; |
| cleanup_subexpr(); |
| --- 4980,4985 ---- |
| |
| *** 5023,5089 **** |
| { |
| /* Messy situation: Need to compare between two |
| * lines. */ |
| ! ccol = reg_startpos[no].col; |
| ! clnum = reg_startpos[no].lnum; |
| ! for (;;) |
| ! { |
| ! /* Since getting one line may invalidate |
| ! * the other, need to make copy. Slow! */ |
| ! if (regline != reg_tofree) |
| ! { |
| ! len = (int)STRLEN(regline); |
| ! if (reg_tofree == NULL |
| ! || len >= (int)reg_tofreelen) |
| ! { |
| ! len += 50; /* get some extra */ |
| ! vim_free(reg_tofree); |
| ! reg_tofree = alloc(len); |
| ! if (reg_tofree == NULL) |
| ! { |
| ! status = RA_FAIL; /* outof memory!*/ |
| ! break; |
| ! } |
| ! reg_tofreelen = len; |
| ! } |
| ! STRCPY(reg_tofree, regline); |
| ! reginput = reg_tofree |
| ! + (reginput - regline); |
| ! regline = reg_tofree; |
| ! } |
| ! |
| ! /* Get the line to compare with. */ |
| ! p = reg_getline(clnum); |
| ! if (clnum == reg_endpos[no].lnum) |
| ! len = reg_endpos[no].col - ccol; |
| ! else |
| ! len = (int)STRLEN(p + ccol); |
| ! |
| ! if (cstrncmp(p + ccol, reginput, &len) != 0) |
| ! { |
| ! status = RA_NOMATCH; /* doesn't match */ |
| ! break; |
| ! } |
| ! if (clnum == reg_endpos[no].lnum) |
| ! break; /* match and at end! */ |
| ! if (reglnum >= reg_maxline) |
| ! { |
| ! status = RA_NOMATCH; /* text too short */ |
| ! break; |
| ! } |
| ! |
| ! /* Advance to next line. */ |
| ! reg_nextline(); |
| ! ++clnum; |
| ! ccol = 0; |
| ! if (got_int) |
| ! { |
| ! status = RA_FAIL; |
| ! break; |
| ! } |
| ! } |
| ! |
| ! /* found a match! Note that regline may now point |
| ! * to a copy of the line, that should not matter. */ |
| } |
| } |
| } |
| --- 5021,5032 ---- |
| { |
| /* Messy situation: Need to compare between two |
| * lines. */ |
| ! status = match_with_backref( |
| ! reg_startpos[no].lnum, |
| ! reg_startpos[no].col, |
| ! reg_endpos[no].lnum, |
| ! reg_endpos[no].col, |
| ! NULL); |
| } |
| } |
| } |
| |
| *** 6505,6510 **** |
| --- 6448,6522 ---- |
| return val == n; |
| } |
| |
| + /* |
| + * Check whether a backreference matches. |
| + * Returns RA_FAIL, RA_NOMATCH or RA_MATCH. |
| + * If "bytelen" is not NULL, it is set to the bytelength of the whole match. |
| + */ |
| + static int |
| + match_with_backref(start_lnum, start_col, end_lnum, end_col, bytelen) |
| + linenr_T start_lnum; |
| + colnr_T start_col; |
| + linenr_T end_lnum; |
| + colnr_T end_col; |
| + int *bytelen; |
| + { |
| + linenr_T clnum = start_lnum; |
| + colnr_T ccol = start_col; |
| + int len; |
| + char_u *p; |
| + |
| + if (bytelen != NULL) |
| + *bytelen = 0; |
| + for (;;) |
| + { |
| + /* Since getting one line may invalidate the other, need to make copy. |
| + * Slow! */ |
| + if (regline != reg_tofree) |
| + { |
| + len = (int)STRLEN(regline); |
| + if (reg_tofree == NULL || len >= (int)reg_tofreelen) |
| + { |
| + len += 50; /* get some extra */ |
| + vim_free(reg_tofree); |
| + reg_tofree = alloc(len); |
| + if (reg_tofree == NULL) |
| + return RA_FAIL; /* out of memory!*/ |
| + reg_tofreelen = len; |
| + } |
| + STRCPY(reg_tofree, regline); |
| + reginput = reg_tofree + (reginput - regline); |
| + regline = reg_tofree; |
| + } |
| + |
| + /* Get the line to compare with. */ |
| + p = reg_getline(clnum); |
| + if (clnum == end_lnum) |
| + len = end_col - ccol; |
| + else |
| + len = (int)STRLEN(p + ccol); |
| + |
| + if (cstrncmp(p + ccol, reginput, &len) != 0) |
| + return RA_NOMATCH; /* doesn't match */ |
| + if (bytelen != NULL) |
| + *bytelen += len; |
| + if (clnum == end_lnum) |
| + break; /* match and at end! */ |
| + if (reglnum >= reg_maxline) |
| + return RA_NOMATCH; /* text too short */ |
| + |
| + /* Advance to next line. */ |
| + reg_nextline(); |
| + ++clnum; |
| + ccol = 0; |
| + if (got_int) |
| + return RA_FAIL; |
| + } |
| + |
| + /* found a match! Note that regline may now point to a copy of the line, |
| + * that should not matter. */ |
| + return RA_MATCH; |
| + } |
| |
| #ifdef BT_REGEXP_DUMP |
| |
| |
| |
| |
| *** 4367,4380 **** |
| if (sub->list.multi[subidx].start.lnum < 0 |
| || sub->list.multi[subidx].end.lnum < 0) |
| goto retempty; |
| ! /* TODO: line breaks */ |
| ! len = sub->list.multi[subidx].end.col |
| ! - sub->list.multi[subidx].start.col; |
| ! if (cstrncmp(regline + sub->list.multi[subidx].start.col, |
| ! reginput, &len) == 0) |
| { |
| ! *bytelen = len; |
| ! return TRUE; |
| } |
| } |
| else |
| --- 4367,4393 ---- |
| if (sub->list.multi[subidx].start.lnum < 0 |
| || sub->list.multi[subidx].end.lnum < 0) |
| goto retempty; |
| ! if (sub->list.multi[subidx].start.lnum == reglnum |
| ! && sub->list.multi[subidx].end.lnum == reglnum) |
| { |
| ! len = sub->list.multi[subidx].end.col |
| ! - sub->list.multi[subidx].start.col; |
| ! if (cstrncmp(regline + sub->list.multi[subidx].start.col, |
| ! reginput, &len) == 0) |
| ! { |
| ! *bytelen = len; |
| ! return TRUE; |
| ! } |
| ! } |
| ! else |
| ! { |
| ! if (match_with_backref( |
| ! sub->list.multi[subidx].start.lnum, |
| ! sub->list.multi[subidx].start.col, |
| ! sub->list.multi[subidx].end.lnum, |
| ! sub->list.multi[subidx].end.col, |
| ! bytelen) == RA_MATCH) |
| ! return TRUE; |
| } |
| } |
| else |
| |
| |
| |
| *** 486,491 **** |
| --- 486,497 ---- |
| :.yank |
| Gop:" |
| :" |
| + :" Check using a backref matching in a previous line |
| + /^Backref: |
| + /\v.*\/(.*)\n.*\/\1$ |
| + :.yank |
| + Gop:" |
| + :" |
| :" Check a pattern with a look beind crossing a line boundary |
| /^Behind: |
| /\(<\_[xy]\+\)\@3<=start |
| |
| *** 566,571 **** |
| --- 572,584 ---- |
| b |
| c |
| |
| + Backref: |
| + ./Dir1/Dir2/zyxwvuts.txt |
| + ./Dir1/Dir2/abcdefgh.bat |
| + |
| + ./Dir1/Dir2/file1.txt |
| + ./OtherDir1/OtherDir2/file1.txt |
| + |
| Behind: |
| asdfasd<yyy |
| xxstart1 |
| |
| |
| |
| *** 920,925 **** |
| --- 920,927 ---- |
| |
| c |
| |
| + ./Dir1/Dir2/file1.txt |
| + |
| xxstart3 |
| |
| thexE thE thExethe |
| |
| |
| |
| *** 730,731 **** |
| --- 730,733 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 1191, |
| /**/ |
| |
| -- |
| hundred-and-one symptoms of being an internet addict: |
| 198. You read all the quotes at Netaholics Anonymous and keep thinking |
| "What's wrong with that?" |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- 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 /// |