⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regexec.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 5 页
字号:
	    {	      mctx.match_last = match_last;	      if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)		{		  re_dfastate_t *pstate = mctx.state_log[match_last];		  mctx.last_node = check_halt_state_context (&mctx, pstate,							     match_last);		}	      if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)		  || dfa->nbackref)		{		  err = prune_impossible_nodes (&mctx);		  if (err == REG_NOERROR)		    break;		  if (BE (err != REG_NOMATCH, 0))		    goto free_return;		  match_last = REG_MISSING;		}	      else		break; /* We found a match.  */	    }	}      match_ctx_clean (&mctx);    }#ifdef DEBUG  assert (match_last != REG_MISSING);  assert (err == REG_NOERROR);#endif  /* Set pmatch[] if we need.  */  if (nmatch > 0)    {      Idx reg_idx;      /* Initialize registers.  */      for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)	pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;      /* Set the points where matching start/end.  */      pmatch[0].rm_so = 0;      pmatch[0].rm_eo = mctx.match_last;      /* FIXME: This function should fail if mctx.match_last exceeds	 the maximum possible regoff_t value.  We need a new error	 code REG_OVERFLOW.  */      if (!preg->no_sub && nmatch > 1)	{	  err = set_regs (preg, &mctx, nmatch, pmatch,			  dfa->has_plural_match && dfa->nbackref > 0);	  if (BE (err != REG_NOERROR, 0))	    goto free_return;	}      /* At last, add the offset to the each registers, since we slided	 the buffers so that we could assume that the matching starts	 from 0.  */      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)	if (pmatch[reg_idx].rm_so != -1)	  {#ifdef RE_ENABLE_I18N	    if (BE (mctx.input.offsets_needed != 0, 0))	      {		pmatch[reg_idx].rm_so =		  (pmatch[reg_idx].rm_so == mctx.input.valid_len		   ? mctx.input.valid_raw_len		   : mctx.input.offsets[pmatch[reg_idx].rm_so]);		pmatch[reg_idx].rm_eo =		  (pmatch[reg_idx].rm_eo == mctx.input.valid_len		   ? mctx.input.valid_raw_len		   : mctx.input.offsets[pmatch[reg_idx].rm_eo]);	      }#else	    assert (mctx.input.offsets_needed == 0);#endif	    pmatch[reg_idx].rm_so += match_first;	    pmatch[reg_idx].rm_eo += match_first;	  }      for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)	{	  pmatch[nmatch + reg_idx].rm_so = -1;	  pmatch[nmatch + reg_idx].rm_eo = -1;	}      if (dfa->subexp_map)        for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)          if (dfa->subexp_map[reg_idx] != reg_idx)            {              pmatch[reg_idx + 1].rm_so                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;              pmatch[reg_idx + 1].rm_eo                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;            }    } free_return:  re_free (mctx.state_log);  if (dfa->nbackref)    match_ctx_free (&mctx);  re_string_destruct (&mctx.input);  return err;}static reg_errcode_tinternal_functionprune_impossible_nodes (re_match_context_t *mctx){  const re_dfa_t *const dfa = mctx->dfa;  Idx halt_node, match_last;  reg_errcode_t ret;  re_dfastate_t **sifted_states;  re_dfastate_t **lim_states = NULL;  re_sift_context_t sctx;#ifdef DEBUG  assert (mctx->state_log != NULL);#endif  match_last = mctx->match_last;  halt_node = mctx->last_node;  /* Avoid overflow.  */  if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0))    return REG_ESPACE;  sifted_states = re_malloc (re_dfastate_t *, match_last + 1);  if (BE (sifted_states == NULL, 0))    {      ret = REG_ESPACE;      goto free_return;    }  if (dfa->nbackref)    {      lim_states = re_malloc (re_dfastate_t *, match_last + 1);      if (BE (lim_states == NULL, 0))	{	  ret = REG_ESPACE;	  goto free_return;	}      while (1)	{	  memset (lim_states, '\0',		  sizeof (re_dfastate_t *) * (match_last + 1));	  sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,			 match_last);	  ret = sift_states_backward (mctx, &sctx);	  re_node_set_free (&sctx.limits);	  if (BE (ret != REG_NOERROR, 0))	      goto free_return;	  if (sifted_states[0] != NULL || lim_states[0] != NULL)	    break;	  do	    {	      --match_last;	      if (! REG_VALID_INDEX (match_last))		{		  ret = REG_NOMATCH;		  goto free_return;		}	    } while (mctx->state_log[match_last] == NULL		     || !mctx->state_log[match_last]->halt);	  halt_node = check_halt_state_context (mctx,						mctx->state_log[match_last],						match_last);	}      ret = merge_state_array (dfa, sifted_states, lim_states,			       match_last + 1);      re_free (lim_states);      lim_states = NULL;      if (BE (ret != REG_NOERROR, 0))	goto free_return;    }  else    {      sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);      ret = sift_states_backward (mctx, &sctx);      re_node_set_free (&sctx.limits);      if (BE (ret != REG_NOERROR, 0))	goto free_return;    }  re_free (mctx->state_log);  mctx->state_log = sifted_states;  sifted_states = NULL;  mctx->last_node = halt_node;  mctx->match_last = match_last;  ret = REG_NOERROR; free_return:  re_free (sifted_states);  re_free (lim_states);  return ret;}/* Acquire an initial state and return it.   We must select appropriate initial state depending on the context,   since initial states may have constraints like "\<", "^", etc..  */static inline re_dfastate_t *__attribute ((always_inline)) internal_functionacquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,			    Idx idx){  const re_dfa_t *const dfa = mctx->dfa;  if (dfa->init_state->has_constraint)    {      unsigned int context;      context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);      if (IS_WORD_CONTEXT (context))	return dfa->init_state_word;      else if (IS_ORDINARY_CONTEXT (context))	return dfa->init_state;      else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))	return dfa->init_state_begbuf;      else if (IS_NEWLINE_CONTEXT (context))	return dfa->init_state_nl;      else if (IS_BEGBUF_CONTEXT (context))	{	  /* It is relatively rare case, then calculate on demand.  */	  return re_acquire_state_context (err, dfa,					   dfa->init_state->entrance_nodes,					   context);	}      else	/* Must not happen?  */	return dfa->init_state;    }  else    return dfa->init_state;}/* Check whether the regular expression match input string INPUT or not,   and return the index where the matching end.  Return REG_MISSING if   there is no match, and return REG_ERROR in case of an error.   FL_LONGEST_MATCH means we want the POSIX longest matching.   If P_MATCH_FIRST is not NULL, and the match fails, it is set to the   next place where we may want to try matching.   Note that the matcher assume that the maching starts from the current   index of the buffer.  */static Idxinternal_functioncheck_matching (re_match_context_t *mctx, bool fl_longest_match,		Idx *p_match_first){  const re_dfa_t *const dfa = mctx->dfa;  reg_errcode_t err;  Idx match = 0;  Idx match_last = REG_MISSING;  Idx cur_str_idx = re_string_cur_idx (&mctx->input);  re_dfastate_t *cur_state;  bool at_init_state = p_match_first != NULL;  Idx next_start_idx = cur_str_idx;  err = REG_NOERROR;  cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);  /* An initial state must not be NULL (invalid).  */  if (BE (cur_state == NULL, 0))    {      assert (err == REG_ESPACE);      return REG_ERROR;    }  if (mctx->state_log != NULL)    {      mctx->state_log[cur_str_idx] = cur_state;      /* Check OP_OPEN_SUBEXP in the initial state in case that we use them	 later.  E.g. Processing back references.  */      if (BE (dfa->nbackref, 0))	{	  at_init_state = false;	  err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);	  if (BE (err != REG_NOERROR, 0))	    return err;	  if (cur_state->has_backref)	    {	      err = transit_state_bkref (mctx, &cur_state->nodes);	      if (BE (err != REG_NOERROR, 0))	        return err;	    }	}    }  /* If the RE accepts NULL string.  */  if (BE (cur_state->halt, 0))    {      if (!cur_state->has_constraint	  || check_halt_state_context (mctx, cur_state, cur_str_idx))	{	  if (!fl_longest_match)	    return cur_str_idx;	  else	    {	      match_last = cur_str_idx;	      match = 1;	    }	}    }  while (!re_string_eoi (&mctx->input))    {      re_dfastate_t *old_state = cur_state;      Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1;      if (BE (next_char_idx >= mctx->input.bufs_len, 0)          || (BE (next_char_idx >= mctx->input.valid_len, 0)              && mctx->input.valid_len < mctx->input.len))        {          err = extend_buffers (mctx);          if (BE (err != REG_NOERROR, 0))	    {	      assert (err == REG_ESPACE);	      return REG_ERROR;	    }        }      cur_state = transit_state (&err, mctx, cur_state);      if (mctx->state_log != NULL)	cur_state = merge_state_with_log (&err, mctx, cur_state);      if (cur_state == NULL)	{	  /* Reached the invalid state or an error.  Try to recover a valid	     state using the state log, if available and if we have not	     already found a valid (even if not the longest) match.  */	  if (BE (err != REG_NOERROR, 0))	    return REG_ERROR;	  if (mctx->state_log == NULL	      || (match && !fl_longest_match)	      || (cur_state = find_recover_state (&err, mctx)) == NULL)	    break;	}      if (BE (at_init_state, 0))	{	  if (old_state == cur_state)	    next_start_idx = next_char_idx;	  else	    at_init_state = false;	}      if (cur_state->halt)	{	  /* Reached a halt state.	     Check the halt state can satisfy the current context.  */	  if (!cur_state->has_constraint	      || check_halt_state_context (mctx, cur_state,					   re_string_cur_idx (&mctx->input)))	    {	      /* We found an appropriate halt state.  */	      match_last = re_string_cur_idx (&mctx->input);	      match = 1;	      /* We found a match, do not modify match_first below.  */	      p_match_first = NULL;	      if (!fl_longest_match)		break;	    }	}    }  if (p_match_first)    *p_match_first += next_start_idx;  return match_last;}/* Check NODE match the current context.  */static boolinternal_functioncheck_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context){  re_token_type_t type = dfa->nodes[node].type;  unsigned int constraint = dfa->nodes[node].constraint;  if (type != END_OF_RE)    return false;  if (!constraint)    return true;  if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))    return false;  return true;}/* Check the halt state STATE match the current context.   Return 0 if not match, if the node, STATE has, is a halt node and   match the context, return the node.  */static Idxinternal_functioncheck_halt_state_context (const re_match_context_t *mctx,			  const re_dfastate_t *state, Idx idx){  Idx i;  unsigned int context;#ifdef DEBUG  assert (state->halt);#endif  context = re_string_context_at (&mctx->input, idx, mctx->eflags);  for (i = 0; i < state->nodes.nelem; ++i)    if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))      return state->nodes.elems[i];  return 0;}/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA   corresponding to the DFA).   Return the destination node, and update EPS_VIA_NODES;   return REG_MISSING in case of errors.  */static Idxinternal_functionproceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,		   Idx *pidx, Idx node, re_node_set *eps_via_nodes,		   struct re_fail_stack_t *fs){  const re_dfa_t *const dfa = mctx->dfa;  Idx i;  bool ok;  if (IS_EPSILON_NODE (dfa->nodes[node].type))    {      re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;      re_node_set *edests = &dfa->edests[node];      Idx dest_node;      ok = re_node_set_insert (eps_via_nodes, node);      if (BE (! ok, 0))	return REG_ERROR;      /* Pick up a valid destination, or return REG_MISSING if none	 is found.  */      for (dest_node = REG_MISSING, i = 0; i < edests->nelem; ++i)	{	  Idx candidate = edests->elems[i];	  if (!re_node_set_contains (cur_nodes, candidate))	    continue;          if (dest_node == REG_MISSING)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -