@@ -3519,6 +3519,7 @@ static void save_se_one __ARGS((save_se_T *savep, char_u **pp));
35193519 *(pp) = (savep)->se_u.ptr; }
35203520
35213521static 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 ));
35223523static int regmatch __ARGS ((char_u * prog ));
35233524static 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
0 commit comments