1
0
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:
Bram Moolenaar
2013-06-14 20:31:28 +02:00
parent 6e70736cbc
commit 580abea48a
5 changed files with 113 additions and 71 deletions

View File

@@ -3519,6 +3519,7 @@ static void save_se_one __ARGS((save_se_T *savep, char_u **pp));
*(pp) = (savep)->se_u.ptr; } *(pp) = (savep)->se_u.ptr; }
static int re_num_cmp __ARGS((long_u val, char_u *scan)); 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 regmatch __ARGS((char_u *prog));
static int regrepeat __ARGS((char_u *p, long maxcount)); static int regrepeat __ARGS((char_u *p, long maxcount));
@@ -4979,9 +4980,6 @@ regmatch(scan)
case BACKREF + 9: case BACKREF + 9:
{ {
int len; int len;
linenr_T clnum;
colnr_T ccol;
char_u *p;
no = op - BACKREF; no = op - BACKREF;
cleanup_subexpr(); cleanup_subexpr();
@@ -5023,67 +5021,12 @@ regmatch(scan)
{ {
/* Messy situation: Need to compare between two /* Messy situation: Need to compare between two
* lines. */ * lines. */
ccol = reg_startpos[no].col; status = match_with_backref(
clnum = reg_startpos[no].lnum; reg_startpos[no].lnum,
for (;;) reg_startpos[no].col,
{ reg_endpos[no].lnum,
/* Since getting one line may invalidate reg_endpos[no].col,
* the other, need to make copy. Slow! */ NULL);
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. */
} }
} }
} }
@@ -6505,6 +6448,75 @@ re_num_cmp(val, scan)
return val == n; 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 #ifdef BT_REGEXP_DUMP

View File

@@ -4367,14 +4367,27 @@ retempty:
if (sub->list.multi[subidx].start.lnum < 0 if (sub->list.multi[subidx].start.lnum < 0
|| sub->list.multi[subidx].end.lnum < 0) || sub->list.multi[subidx].end.lnum < 0)
goto retempty; goto retempty;
/* TODO: line breaks */ if (sub->list.multi[subidx].start.lnum == reglnum
len = sub->list.multi[subidx].end.col && sub->list.multi[subidx].end.lnum == reglnum)
- sub->list.multi[subidx].start.col;
if (cstrncmp(regline + sub->list.multi[subidx].start.col,
reginput, &len) == 0)
{ {
*bytelen = len; len = sub->list.multi[subidx].end.col
return TRUE; - 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 else

View File

@@ -486,6 +486,12 @@ y$Gop:"
:.yank :.yank
Gop:" 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 :" Check a pattern with a look beind crossing a line boundary
/^Behind: /^Behind:
/\(<\_[xy]\+\)\@3<=start /\(<\_[xy]\+\)\@3<=start
@@ -566,6 +572,13 @@ a
b b
c c
Backref:
./Dir1/Dir2/zyxwvuts.txt
./Dir1/Dir2/abcdefgh.bat
./Dir1/Dir2/file1.txt
./OtherDir1/OtherDir2/file1.txt
Behind: Behind:
asdfasd<yyy asdfasd<yyy
xxstart1 xxstart1

View File

@@ -920,6 +920,8 @@ ghi
c c
./Dir1/Dir2/file1.txt
xxstart3 xxstart3
thexE thE thExethe thexE thE thExethe

View File

@@ -728,6 +728,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1191,
/**/ /**/
1190, 1190,
/**/ /**/