Skip to content

Commit 6cd03cb

Browse files
committed
updated for version 7.3.1191
Problem: Backreference to previous line doesn't work. (Lech Lorens) Solution: Implement looking in another line.
1 parent 00ee0a5 commit 6cd03cb

5 files changed

Lines changed: 113 additions & 71 deletions

File tree

src/regexp.c

Lines changed: 76 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3519,6 +3519,7 @@ static void save_se_one __ARGS((save_se_T *savep, char_u **pp));
35193519
*(pp) = (savep)->se_u.ptr; }
35203520

35213521
static int re_num_cmp __ARGS((long_u val, char_u *scan));
3522+
static int match_with_backref __ARGS((linenr_T start_lnum, colnr_T start_col, linenr_T end_lnum, colnr_T end_col, int *bytelen));
35223523
static int regmatch __ARGS((char_u *prog));
35233524
static int regrepeat __ARGS((char_u *p, long maxcount));
35243525

@@ -4979,9 +4980,6 @@ regmatch(scan)
49794980
case BACKREF + 9:
49804981
{
49814982
int len;
4982-
linenr_T clnum;
4983-
colnr_T ccol;
4984-
char_u *p;
49854983

49864984
no = op - BACKREF;
49874985
cleanup_subexpr();
@@ -5023,67 +5021,12 @@ regmatch(scan)
50235021
{
50245022
/* Messy situation: Need to compare between two
50255023
* lines. */
5026-
ccol = reg_startpos[no].col;
5027-
clnum = reg_startpos[no].lnum;
5028-
for (;;)
5029-
{
5030-
/* Since getting one line may invalidate
5031-
* the other, need to make copy. Slow! */
5032-
if (regline != reg_tofree)
5033-
{
5034-
len = (int)STRLEN(regline);
5035-
if (reg_tofree == NULL
5036-
|| len >= (int)reg_tofreelen)
5037-
{
5038-
len += 50; /* get some extra */
5039-
vim_free(reg_tofree);
5040-
reg_tofree = alloc(len);
5041-
if (reg_tofree == NULL)
5042-
{
5043-
status = RA_FAIL; /* outof memory!*/
5044-
break;
5045-
}
5046-
reg_tofreelen = len;
5047-
}
5048-
STRCPY(reg_tofree, regline);
5049-
reginput = reg_tofree
5050-
+ (reginput - regline);
5051-
regline = reg_tofree;
5052-
}
5053-
5054-
/* Get the line to compare with. */
5055-
p = reg_getline(clnum);
5056-
if (clnum == reg_endpos[no].lnum)
5057-
len = reg_endpos[no].col - ccol;
5058-
else
5059-
len = (int)STRLEN(p + ccol);
5060-
5061-
if (cstrncmp(p + ccol, reginput, &len) != 0)
5062-
{
5063-
status = RA_NOMATCH; /* doesn't match */
5064-
break;
5065-
}
5066-
if (clnum == reg_endpos[no].lnum)
5067-
break; /* match and at end! */
5068-
if (reglnum >= reg_maxline)
5069-
{
5070-
status = RA_NOMATCH; /* text too short */
5071-
break;
5072-
}
5073-
5074-
/* Advance to next line. */
5075-
reg_nextline();
5076-
++clnum;
5077-
ccol = 0;
5078-
if (got_int)
5079-
{
5080-
status = RA_FAIL;
5081-
break;
5082-
}
5083-
}
5084-
5085-
/* found a match! Note that regline may now point
5086-
* to a copy of the line, that should not matter. */
5024+
status = match_with_backref(
5025+
reg_startpos[no].lnum,
5026+
reg_startpos[no].col,
5027+
reg_endpos[no].lnum,
5028+
reg_endpos[no].col,
5029+
NULL);
50875030
}
50885031
}
50895032
}
@@ -6505,6 +6448,75 @@ re_num_cmp(val, scan)
65056448
return val == n;
65066449
}
65076450

6451+
/*
6452+
* Check whether a backreference matches.
6453+
* Returns RA_FAIL, RA_NOMATCH or RA_MATCH.
6454+
* If "bytelen" is not NULL, it is set to the bytelength of the whole match.
6455+
*/
6456+
static int
6457+
match_with_backref(start_lnum, start_col, end_lnum, end_col, bytelen)
6458+
linenr_T start_lnum;
6459+
colnr_T start_col;
6460+
linenr_T end_lnum;
6461+
colnr_T end_col;
6462+
int *bytelen;
6463+
{
6464+
linenr_T clnum = start_lnum;
6465+
colnr_T ccol = start_col;
6466+
int len;
6467+
char_u *p;
6468+
6469+
if (bytelen != NULL)
6470+
*bytelen = 0;
6471+
for (;;)
6472+
{
6473+
/* Since getting one line may invalidate the other, need to make copy.
6474+
* Slow! */
6475+
if (regline != reg_tofree)
6476+
{
6477+
len = (int)STRLEN(regline);
6478+
if (reg_tofree == NULL || len >= (int)reg_tofreelen)
6479+
{
6480+
len += 50; /* get some extra */
6481+
vim_free(reg_tofree);
6482+
reg_tofree = alloc(len);
6483+
if (reg_tofree == NULL)
6484+
return RA_FAIL; /* out of memory!*/
6485+
reg_tofreelen = len;
6486+
}
6487+
STRCPY(reg_tofree, regline);
6488+
reginput = reg_tofree + (reginput - regline);
6489+
regline = reg_tofree;
6490+
}
6491+
6492+
/* Get the line to compare with. */
6493+
p = reg_getline(clnum);
6494+
if (clnum == end_lnum)
6495+
len = end_col - ccol;
6496+
else
6497+
len = (int)STRLEN(p + ccol);
6498+
6499+
if (cstrncmp(p + ccol, reginput, &len) != 0)
6500+
return RA_NOMATCH; /* doesn't match */
6501+
if (bytelen != NULL)
6502+
*bytelen += len;
6503+
if (clnum == end_lnum)
6504+
break; /* match and at end! */
6505+
if (reglnum >= reg_maxline)
6506+
return RA_NOMATCH; /* text too short */
6507+
6508+
/* Advance to next line. */
6509+
reg_nextline();
6510+
++clnum;
6511+
ccol = 0;
6512+
if (got_int)
6513+
return RA_FAIL;
6514+
}
6515+
6516+
/* found a match! Note that regline may now point to a copy of the line,
6517+
* that should not matter. */
6518+
return RA_MATCH;
6519+
}
65086520

65096521
#ifdef BT_REGEXP_DUMP
65106522

src/regexp_nfa.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4367,14 +4367,27 @@ match_backref(sub, subidx, bytelen)
43674367
if (sub->list.multi[subidx].start.lnum < 0
43684368
|| sub->list.multi[subidx].end.lnum < 0)
43694369
goto retempty;
4370-
/* TODO: line breaks */
4371-
len = sub->list.multi[subidx].end.col
4372-
- sub->list.multi[subidx].start.col;
4373-
if (cstrncmp(regline + sub->list.multi[subidx].start.col,
4374-
reginput, &len) == 0)
4370+
if (sub->list.multi[subidx].start.lnum == reglnum
4371+
&& sub->list.multi[subidx].end.lnum == reglnum)
43754372
{
4376-
*bytelen = len;
4377-
return TRUE;
4373+
len = sub->list.multi[subidx].end.col
4374+
- sub->list.multi[subidx].start.col;
4375+
if (cstrncmp(regline + sub->list.multi[subidx].start.col,
4376+
reginput, &len) == 0)
4377+
{
4378+
*bytelen = len;
4379+
return TRUE;
4380+
}
4381+
}
4382+
else
4383+
{
4384+
if (match_with_backref(
4385+
sub->list.multi[subidx].start.lnum,
4386+
sub->list.multi[subidx].start.col,
4387+
sub->list.multi[subidx].end.lnum,
4388+
sub->list.multi[subidx].end.col,
4389+
bytelen) == RA_MATCH)
4390+
return TRUE;
43784391
}
43794392
}
43804393
else

src/testdir/test64.in

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,12 @@ y$Gop:"
486486
:.yank
487487
Gop:"
488488
:"
489+
:" Check using a backref matching in a previous line
490+
/^Backref:
491+
/\v.*\/(.*)\n.*\/\1$
492+
:.yank
493+
Gop:"
494+
:"
489495
:" Check a pattern with a look beind crossing a line boundary
490496
/^Behind:
491497
/\(<\_[xy]\+\)\@3<=start
@@ -566,6 +572,13 @@ a
566572
b
567573
c
568574

575+
Backref:
576+
./Dir1/Dir2/zyxwvuts.txt
577+
./Dir1/Dir2/abcdefgh.bat
578+
579+
./Dir1/Dir2/file1.txt
580+
./OtherDir1/OtherDir2/file1.txt
581+
569582
Behind:
570583
asdfasd<yyy
571584
xxstart1

src/testdir/test64.ok

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,8 @@ ghi
920920

921921
c
922922

923+
./Dir1/Dir2/file1.txt
924+
923925
xxstart3
924926

925927
thexE thE thExethe

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,8 @@ static char *(features[]) =
728728

729729
static int included_patches[] =
730730
{ /* Add new patch number below this line */
731+
/**/
732+
1191,
731733
/**/
732734
1190,
733735
/**/

0 commit comments

Comments
 (0)