@@ -4340,6 +4340,9 @@ state_in_list(
43404340 return FALSE;
43414341}
43424342
4343+ /* Offset used for "off" by addstate_here(). */
4344+ #define ADDSTATE_HERE_OFFSET 10
4345+
43434346/*
43444347 * Add "state" and possibly what follows to state list ".".
43454348 * Returns "subs_arg", possibly copied into temp_subs.
@@ -4350,11 +4353,16 @@ addstate(
43504353 nfa_state_T * state , /* state to update */
43514354 regsubs_T * subs_arg , /* pointers to subexpressions */
43524355 nfa_pim_T * pim , /* postponed look-behind match */
4353- int off ) /* byte offset, when -1 go to next line */
4356+ int off_arg ) /* byte offset, when -1 go to next line */
43544357{
43554358 int subidx ;
4359+ int off = off_arg ;
4360+ int add_here = FALSE;
4361+ int listindex = 0 ;
4362+ int k ;
4363+ int found = FALSE;
43564364 nfa_thread_T * thread ;
4357- lpos_T save_lpos ;
4365+ struct multipos save_multipos ;
43584366 int save_in_use ;
43594367 char_u * save_ptr ;
43604368 int i ;
@@ -4365,6 +4373,13 @@ addstate(
43654373 int did_print = FALSE;
43664374#endif
43674375
4376+ if (off_arg <= - ADDSTATE_HERE_OFFSET )
4377+ {
4378+ add_here = TRUE;
4379+ off = 0 ;
4380+ listindex = - (off_arg + ADDSTATE_HERE_OFFSET );
4381+ }
4382+
43684383 switch (state -> c )
43694384 {
43704385 case NFA_NCLOSE :
@@ -4448,13 +4463,28 @@ addstate(
44484463 if (!nfa_has_backref && pim == NULL && !l -> has_pim
44494464 && state -> c != NFA_MATCH )
44504465 {
4466+ /* When called from addstate_here() do insert before
4467+ * existing states. */
4468+ if (add_here )
4469+ {
4470+ for (k = 0 ; k < l -> n && k < listindex ; ++ k )
4471+ if (l -> t [k ].state -> id == state -> id )
4472+ {
4473+ found = TRUE;
4474+ break ;
4475+ }
4476+ }
4477+ if (!add_here || found )
4478+ {
44514479skip_add :
44524480#ifdef ENABLE_LOG
4453- nfa_set_code (state -> c );
4454- fprintf (log_fd , "> Not adding state %d to list %d. char %d: %s\n" ,
4455- abs (state -> id ), l -> id , state -> c , code );
4481+ nfa_set_code (state -> c );
4482+ fprintf (log_fd , "> Not adding state %d to list %d. char %d: %s pim: %s has_pim: %d found: %d\n" ,
4483+ abs (state -> id ), l -> id , state -> c , code ,
4484+ pim == NULL ? "NULL" : "yes" , l -> has_pim , found );
44564485#endif
4457- return subs ;
4486+ return subs ;
4487+ }
44584488 }
44594489
44604490 /* Do not add the state again when it exists with the same
@@ -4519,14 +4549,14 @@ addstate(
45194549
45204550 case NFA_SPLIT :
45214551 /* order matters here */
4522- subs = addstate (l , state -> out , subs , pim , off );
4523- subs = addstate (l , state -> out1 , subs , pim , off );
4552+ subs = addstate (l , state -> out , subs , pim , off_arg );
4553+ subs = addstate (l , state -> out1 , subs , pim , off_arg );
45244554 break ;
45254555
45264556 case NFA_EMPTY :
45274557 case NFA_NOPEN :
45284558 case NFA_NCLOSE :
4529- subs = addstate (l , state -> out , subs , pim , off );
4559+ subs = addstate (l , state -> out , subs , pim , off_arg );
45304560 break ;
45314561
45324562 case NFA_MOPEN :
@@ -4572,17 +4602,15 @@ addstate(
45724602
45734603 /* avoid compiler warnings */
45744604 save_ptr = NULL ;
4575- save_lpos .lnum = 0 ;
4576- save_lpos .col = 0 ;
4605+ vim_memset (& save_multipos , 0 , sizeof (save_multipos ));
45774606
45784607 /* Set the position (with "off" added) in the subexpression. Save
45794608 * and restore it when it was in use. Otherwise fill any gap. */
45804609 if (REG_MULTI )
45814610 {
45824611 if (subidx < sub -> in_use )
45834612 {
4584- save_lpos .lnum = sub -> list .multi [subidx ].start_lnum ;
4585- save_lpos .col = sub -> list .multi [subidx ].start_col ;
4613+ save_multipos = sub -> list .multi [subidx ];
45864614 save_in_use = -1 ;
45874615 }
45884616 else
@@ -4628,7 +4656,7 @@ addstate(
46284656 sub -> list .line [subidx ].start = reginput + off ;
46294657 }
46304658
4631- subs = addstate (l , state -> out , subs , pim , off );
4659+ subs = addstate (l , state -> out , subs , pim , off_arg );
46324660 /* "subs" may have changed, need to set "sub" again */
46334661#ifdef FEAT_SYN_HL
46344662 if (state -> c >= NFA_ZOPEN && state -> c <= NFA_ZOPEN9 )
@@ -4640,10 +4668,7 @@ addstate(
46404668 if (save_in_use == -1 )
46414669 {
46424670 if (REG_MULTI )
4643- {
4644- sub -> list .multi [subidx ].start_lnum = save_lpos .lnum ;
4645- sub -> list .multi [subidx ].start_col = save_lpos .col ;
4646- }
4671+ sub -> list .multi [subidx ] = save_multipos ;
46474672 else
46484673 sub -> list .line [subidx ].start = save_ptr ;
46494674 }
@@ -4657,7 +4682,7 @@ addstate(
46574682 : subs -> norm .list .line [0 ].end != NULL ))
46584683 {
46594684 /* Do not overwrite the position set by \ze. */
4660- subs = addstate (l , state -> out , subs , pim , off );
4685+ subs = addstate (l , state -> out , subs , pim , off_arg );
46614686 break ;
46624687 }
46634688 case NFA_MCLOSE1 :
@@ -4707,8 +4732,7 @@ addstate(
47074732 sub -> in_use = subidx + 1 ;
47084733 if (REG_MULTI )
47094734 {
4710- save_lpos .lnum = sub -> list .multi [subidx ].end_lnum ;
4711- save_lpos .col = sub -> list .multi [subidx ].end_col ;
4735+ save_multipos = sub -> list .multi [subidx ];
47124736 if (off == -1 )
47134737 {
47144738 sub -> list .multi [subidx ].end_lnum = reglnum + 1 ;
@@ -4728,11 +4752,10 @@ addstate(
47284752 save_ptr = sub -> list .line [subidx ].end ;
47294753 sub -> list .line [subidx ].end = reginput + off ;
47304754 /* avoid compiler warnings */
4731- save_lpos .lnum = 0 ;
4732- save_lpos .col = 0 ;
4755+ vim_memset (& save_multipos , 0 , sizeof (save_multipos ));
47334756 }
47344757
4735- subs = addstate (l , state -> out , subs , pim , off );
4758+ subs = addstate (l , state -> out , subs , pim , off_arg );
47364759 /* "subs" may have changed, need to set "sub" again */
47374760#ifdef FEAT_SYN_HL
47384761 if (state -> c >= NFA_ZCLOSE && state -> c <= NFA_ZCLOSE9 )
@@ -4742,10 +4765,7 @@ addstate(
47424765 sub = & subs -> norm ;
47434766
47444767 if (REG_MULTI )
4745- {
4746- sub -> list .multi [subidx ].end_lnum = save_lpos .lnum ;
4747- sub -> list .multi [subidx ].end_col = save_lpos .col ;
4748- }
4768+ sub -> list .multi [subidx ] = save_multipos ;
47494769 else
47504770 sub -> list .line [subidx ].end = save_ptr ;
47514771 sub -> in_use = save_in_use ;
@@ -4772,8 +4792,10 @@ addstate_here(
47724792 int count ;
47734793 int listidx = * ip ;
47744794
4775- /* first add the state(s) at the end, so that we know how many there are */
4776- addstate (l , state , subs , pim , 0 );
4795+ /* First add the state(s) at the end, so that we know how many there are.
4796+ * Pass the listidx as offset (avoids adding another argument to
4797+ * addstate(). */
4798+ addstate (l , state , subs , pim , - listidx - ADDSTATE_HERE_OFFSET );
47774799
47784800 /* when "*ip" was at the end of the list, nothing to do */
47794801 if (listidx + 1 == tlen )
0 commit comments