comparison src/regexp_nfa.c @ 10170:4acacf4081ce v7.4.2355

commit https://github.com/vim/vim/commit/16b3578f355282846f2600ce77fb344950f0b9ce Author: Bram Moolenaar <Bram@vim.org> Date: Fri Sep 9 20:29:50 2016 +0200 patch 7.4.2355 Problem: Regexp fails to match when using "\>\)\?". (Ramel) Solution: When a state is already in the list, but addstate_here() is used and the existing state comes later, add the new state anyway.
author Christian Brabandt <cb@256bit.org>
date Fri, 09 Sep 2016 20:30:07 +0200
parents 3c37899baa8d
children d76ccdacb41e
comparison
equal deleted inserted replaced
10169:fbb82155b1e2 10170:4acacf4081ce
4338 return TRUE; 4338 return TRUE;
4339 } 4339 }
4340 return FALSE; 4340 return FALSE;
4341 } 4341 }
4342 4342
4343 /* Offset used for "off" by addstate_here(). */
4344 #define ADDSTATE_HERE_OFFSET 10
4345
4343 /* 4346 /*
4344 * Add "state" and possibly what follows to state list ".". 4347 * Add "state" and possibly what follows to state list ".".
4345 * Returns "subs_arg", possibly copied into temp_subs. 4348 * Returns "subs_arg", possibly copied into temp_subs.
4346 */ 4349 */
4347 static regsubs_T * 4350 static regsubs_T *
4348 addstate( 4351 addstate(
4349 nfa_list_T *l, /* runtime state list */ 4352 nfa_list_T *l, /* runtime state list */
4350 nfa_state_T *state, /* state to update */ 4353 nfa_state_T *state, /* state to update */
4351 regsubs_T *subs_arg, /* pointers to subexpressions */ 4354 regsubs_T *subs_arg, /* pointers to subexpressions */
4352 nfa_pim_T *pim, /* postponed look-behind match */ 4355 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 */
4354 { 4357 {
4355 int subidx; 4358 int subidx;
4359 int off = off_arg;
4360 int add_here = FALSE;
4361 int listindex = 0;
4362 int k;
4363 int found = FALSE;
4356 nfa_thread_T *thread; 4364 nfa_thread_T *thread;
4357 struct multipos save_multipos; 4365 struct multipos save_multipos;
4358 int save_in_use; 4366 int save_in_use;
4359 char_u *save_ptr; 4367 char_u *save_ptr;
4360 int i; 4368 int i;
4362 regsubs_T *subs = subs_arg; 4370 regsubs_T *subs = subs_arg;
4363 static regsubs_T temp_subs; 4371 static regsubs_T temp_subs;
4364 #ifdef ENABLE_LOG 4372 #ifdef ENABLE_LOG
4365 int did_print = FALSE; 4373 int did_print = FALSE;
4366 #endif 4374 #endif
4375
4376 if (off_arg <= -ADDSTATE_HERE_OFFSET)
4377 {
4378 add_here = TRUE;
4379 off = 0;
4380 listindex = -(off_arg + ADDSTATE_HERE_OFFSET);
4381 }
4367 4382
4368 switch (state->c) 4383 switch (state->c)
4369 { 4384 {
4370 case NFA_NCLOSE: 4385 case NFA_NCLOSE:
4371 case NFA_MCLOSE: 4386 case NFA_MCLOSE:
4446 * when there is a PIM. For NFA_MATCH check the position, 4461 * when there is a PIM. For NFA_MATCH check the position,
4447 * lower position is preferred. */ 4462 * lower position is preferred. */
4448 if (!nfa_has_backref && pim == NULL && !l->has_pim 4463 if (!nfa_has_backref && pim == NULL && !l->has_pim
4449 && state->c != NFA_MATCH) 4464 && state->c != NFA_MATCH)
4450 { 4465 {
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 {
4451 skip_add: 4479 skip_add:
4452 #ifdef ENABLE_LOG 4480 #ifdef ENABLE_LOG
4453 nfa_set_code(state->c); 4481 nfa_set_code(state->c);
4454 fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s\n", 4482 fprintf(log_fd, "> Not adding state %d to list %d. char %d: %s pim: %s has_pim: %d found: %d\n",
4455 abs(state->id), l->id, state->c, code); 4483 abs(state->id), l->id, state->c, code,
4456 #endif 4484 pim == NULL ? "NULL" : "yes", l->has_pim, found);
4457 return subs; 4485 #endif
4486 return subs;
4487 }
4458 } 4488 }
4459 4489
4460 /* Do not add the state again when it exists with the same 4490 /* Do not add the state again when it exists with the same
4461 * positions. */ 4491 * positions. */
4462 if (has_state_with_pos(l, state, subs, pim)) 4492 if (has_state_with_pos(l, state, subs, pim))
4517 case NFA_MATCH: 4547 case NFA_MATCH:
4518 break; 4548 break;
4519 4549
4520 case NFA_SPLIT: 4550 case NFA_SPLIT:
4521 /* order matters here */ 4551 /* order matters here */
4522 subs = addstate(l, state->out, subs, pim, off); 4552 subs = addstate(l, state->out, subs, pim, off_arg);
4523 subs = addstate(l, state->out1, subs, pim, off); 4553 subs = addstate(l, state->out1, subs, pim, off_arg);
4524 break; 4554 break;
4525 4555
4526 case NFA_EMPTY: 4556 case NFA_EMPTY:
4527 case NFA_NOPEN: 4557 case NFA_NOPEN:
4528 case NFA_NCLOSE: 4558 case NFA_NCLOSE:
4529 subs = addstate(l, state->out, subs, pim, off); 4559 subs = addstate(l, state->out, subs, pim, off_arg);
4530 break; 4560 break;
4531 4561
4532 case NFA_MOPEN: 4562 case NFA_MOPEN:
4533 case NFA_MOPEN1: 4563 case NFA_MOPEN1:
4534 case NFA_MOPEN2: 4564 case NFA_MOPEN2:
4624 sub->in_use = subidx + 1; 4654 sub->in_use = subidx + 1;
4625 } 4655 }
4626 sub->list.line[subidx].start = reginput + off; 4656 sub->list.line[subidx].start = reginput + off;
4627 } 4657 }
4628 4658
4629 subs = addstate(l, state->out, subs, pim, off); 4659 subs = addstate(l, state->out, subs, pim, off_arg);
4630 /* "subs" may have changed, need to set "sub" again */ 4660 /* "subs" may have changed, need to set "sub" again */
4631 #ifdef FEAT_SYN_HL 4661 #ifdef FEAT_SYN_HL
4632 if (state->c >= NFA_ZOPEN && state->c <= NFA_ZOPEN9) 4662 if (state->c >= NFA_ZOPEN && state->c <= NFA_ZOPEN9)
4633 sub = &subs->synt; 4663 sub = &subs->synt;
4634 else 4664 else
4650 if (nfa_has_zend && (REG_MULTI 4680 if (nfa_has_zend && (REG_MULTI
4651 ? subs->norm.list.multi[0].end_lnum >= 0 4681 ? subs->norm.list.multi[0].end_lnum >= 0
4652 : subs->norm.list.line[0].end != NULL)) 4682 : subs->norm.list.line[0].end != NULL))
4653 { 4683 {
4654 /* Do not overwrite the position set by \ze. */ 4684 /* Do not overwrite the position set by \ze. */
4655 subs = addstate(l, state->out, subs, pim, off); 4685 subs = addstate(l, state->out, subs, pim, off_arg);
4656 break; 4686 break;
4657 } 4687 }
4658 case NFA_MCLOSE1: 4688 case NFA_MCLOSE1:
4659 case NFA_MCLOSE2: 4689 case NFA_MCLOSE2:
4660 case NFA_MCLOSE3: 4690 case NFA_MCLOSE3:
4723 sub->list.line[subidx].end = reginput + off; 4753 sub->list.line[subidx].end = reginput + off;
4724 /* avoid compiler warnings */ 4754 /* avoid compiler warnings */
4725 vim_memset(&save_multipos, 0, sizeof(save_multipos)); 4755 vim_memset(&save_multipos, 0, sizeof(save_multipos));
4726 } 4756 }
4727 4757
4728 subs = addstate(l, state->out, subs, pim, off); 4758 subs = addstate(l, state->out, subs, pim, off_arg);
4729 /* "subs" may have changed, need to set "sub" again */ 4759 /* "subs" may have changed, need to set "sub" again */
4730 #ifdef FEAT_SYN_HL 4760 #ifdef FEAT_SYN_HL
4731 if (state->c >= NFA_ZCLOSE && state->c <= NFA_ZCLOSE9) 4761 if (state->c >= NFA_ZCLOSE && state->c <= NFA_ZCLOSE9)
4732 sub = &subs->synt; 4762 sub = &subs->synt;
4733 else 4763 else
4760 { 4790 {
4761 int tlen = l->n; 4791 int tlen = l->n;
4762 int count; 4792 int count;
4763 int listidx = *ip; 4793 int listidx = *ip;
4764 4794
4765 /* first add the state(s) at the end, so that we know how many there are */ 4795 /* First add the state(s) at the end, so that we know how many there are.
4766 addstate(l, state, subs, pim, 0); 4796 * Pass the listidx as offset (avoids adding another argument to
4797 * addstate(). */
4798 addstate(l, state, subs, pim, -listidx - ADDSTATE_HERE_OFFSET);
4767 4799
4768 /* when "*ip" was at the end of the list, nothing to do */ 4800 /* when "*ip" was at the end of the list, nothing to do */
4769 if (listidx + 1 == tlen) 4801 if (listidx + 1 == tlen)
4770 return; 4802 return;
4771 4803