forked from aniani/vim
updated for version 7.3.1191
Problem: Backreference to previous line doesn't work. (Lech Lorens) Solution: Implement looking in another line.
This commit is contained in:
140
src/regexp.c
140
src/regexp.c
@@ -3519,6 +3519,7 @@ static void save_se_one __ARGS((save_se_T *savep, char_u **pp));
|
||||
*(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,9 +4980,6 @@ regmatch(scan)
|
||||
case BACKREF + 9:
|
||||
{
|
||||
int len;
|
||||
linenr_T clnum;
|
||||
colnr_T ccol;
|
||||
char_u *p;
|
||||
|
||||
no = op - BACKREF;
|
||||
cleanup_subexpr();
|
||||
@@ -5023,67 +5021,12 @@ regmatch(scan)
|
||||
{
|
||||
/* 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. */
|
||||
status = match_with_backref(
|
||||
reg_startpos[no].lnum,
|
||||
reg_startpos[no].col,
|
||||
reg_endpos[no].lnum,
|
||||
reg_endpos[no].col,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6505,6 +6448,75 @@ re_num_cmp(val, scan)
|
||||
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,7 +4367,9 @@ retempty:
|
||||
if (sub->list.multi[subidx].start.lnum < 0
|
||||
|| sub->list.multi[subidx].end.lnum < 0)
|
||||
goto retempty;
|
||||
/* TODO: line breaks */
|
||||
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,
|
||||
@@ -4378,6 +4380,17 @@ retempty:
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
if (sub->list.line[subidx].start == NULL
|
||||
|| sub->list.line[subidx].end == NULL)
|
||||
|
@@ -486,6 +486,12 @@ y$Gop:"
|
||||
:.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,6 +572,13 @@ a
|
||||
b
|
||||
c
|
||||
|
||||
Backref:
|
||||
./Dir1/Dir2/zyxwvuts.txt
|
||||
./Dir1/Dir2/abcdefgh.bat
|
||||
|
||||
./Dir1/Dir2/file1.txt
|
||||
./OtherDir1/OtherDir2/file1.txt
|
||||
|
||||
Behind:
|
||||
asdfasd<yyy
|
||||
xxstart1
|
||||
|
@@ -920,6 +920,8 @@ ghi
|
||||
|
||||
c
|
||||
|
||||
./Dir1/Dir2/file1.txt
|
||||
|
||||
xxstart3
|
||||
|
||||
thexE thE thExethe
|
||||
|
@@ -728,6 +728,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1191,
|
||||
/**/
|
||||
1190,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user