search.c

来自「linux平台中」· C语言 代码 · 共 725 行 · 第 1/2 页

C
725
字号
#ifdef MBS_SUPPORT		  if (MB_CUR_MAX > 1)		    free(mb_properties);#endif		  return (size_t)-1;		}	      beg += offset;	      /* Narrow down to the line containing the candidate, and		 run it through DFA. */	      end = memchr(beg, eol, buflim - beg);	      end++;#ifdef MBS_SUPPORT	      if (MB_CUR_MAX > 1 && mb_properties[beg - buf] == 0)		continue;#endif	      while (beg > buf && beg[-1] != eol)		--beg;	      if (kwsm.index < kwset_exact_matches)		goto success;	      if (dfaexec (&dfa, beg, end - beg, &backref) == (size_t) -1)		continue;	    }	  else	    {	      /* No good fixed strings; start with DFA. */	      size_t offset = dfaexec (&dfa, beg, buflim - beg, &backref);	      if (offset == (size_t) -1)		break;	      /* Narrow down to the line we've found. */	      beg += offset;	      end = memchr (beg, eol, buflim - beg);	      end++;	      while (beg > buf && beg[-1] != eol)		--beg;	    }	  /* Successful, no backreferences encountered! */	  if (!backref)	    goto success;	}      else	end = beg + size;      /* If we've made it to this point, this means DFA has seen	 a probable match, and we need to run it through Regex. */      for (i = 0; i < pcount; i++)	{	  patterns[i].regexbuf.not_eol = 0;	  if (0 <= (start = re_search (&(patterns[i].regexbuf), beg,				       end - beg - 1, 0,				       end - beg - 1, &(patterns[i].regs))))	    {	      len = patterns[i].regs.end[0] - start;	      if (exact)		{		  *match_size = len;		  return start;		}	      if ((!match_lines && !match_words)		  || (match_lines && len == end - beg - 1))		goto success;	      /* If -w, check if the match aligns with word boundaries.		 We do this iteratively because:		 (a) the line may contain more than one occurence of the		 pattern, and		 (b) Several alternatives in the pattern might be valid at a		 given point, and we may need to consider a shorter one to		 find a word boundary.  */	      if (match_words)		while (start >= 0)		  {		    if ((start == 0 || !WCHAR ((unsigned char) beg[start - 1]))			&& (len == end - beg - 1			    || !WCHAR ((unsigned char) beg[start + len])))		      goto success;		    if (len > 0)		      {			/* Try a shorter length anchored at the same place. */			--len;			patterns[i].regexbuf.not_eol = 1;			len = re_match (&(patterns[i].regexbuf), beg,					start + len, start,					&(patterns[i].regs));		      }		    if (len <= 0)		      {			/* Try looking further on. */			if (start == end - beg - 1)			  break;			++start;			patterns[i].regexbuf.not_eol = 0;			start = re_search (&(patterns[i].regexbuf), beg,					   end - beg - 1,					   start, end - beg - 1 - start,					   &(patterns[i].regs));			len = patterns[i].regs.end[0] - start;		      }		  }	    }	} /* for Regex patterns.  */    } /* for (beg = end ..) */#ifdef MBS_SUPPORT  if (MB_CUR_MAX > 1 && mb_properties)    free (mb_properties);#endif /* MBS_SUPPORT */  return (size_t) -1; success:#ifdef MBS_SUPPORT  if (MB_CUR_MAX > 1 && mb_properties)    free (mb_properties);#endif /* MBS_SUPPORT */  *match_size = end - beg;  return beg - buf;}static voidFcompile (char const *pattern, size_t size){  char const *beg, *lim, *err;  kwsinit ();  beg = pattern;  do    {      for (lim = beg; lim < pattern + size && *lim != '\n'; ++lim)	;      if ((err = kwsincr (kwset, beg, lim - beg)) != 0)	error (2, 0, err);      if (lim < pattern + size)	++lim;      beg = lim;    }  while (beg < pattern + size);  if ((err = kwsprep (kwset)) != 0)    error (2, 0, err);}static size_tFexecute (char const *buf, size_t size, size_t *match_size, int exact){  register char const *beg, *try, *end;  register size_t len;  char eol = eolbyte;  struct kwsmatch kwsmatch;#ifdef MBS_SUPPORT  char *mb_properties;  if (MB_CUR_MAX > 1)    mb_properties = check_multibyte_string (buf, size);#endif /* MBS_SUPPORT */  for (beg = buf; beg <= buf + size; ++beg)    {      size_t offset = kwsexec (kwset, beg, buf + size - beg, &kwsmatch);      if (offset == (size_t) -1)	{#ifdef MBS_SUPPORT	  if (MB_CUR_MAX > 1)	    free(mb_properties);#endif /* MBS_SUPPORT */	  return offset;	}#ifdef MBS_SUPPORT      if (MB_CUR_MAX > 1 && mb_properties[offset+beg-buf] == 0)	continue; /* It is a part of multibyte character.  */#endif /* MBS_SUPPORT */      beg += offset;      len = kwsmatch.size[0];      if (exact)	{	  *match_size = len;#ifdef MBS_SUPPORT	  if (MB_CUR_MAX > 1)	    free (mb_properties);#endif /* MBS_SUPPORT */	  return beg - buf;	}      if (match_lines)	{	  if (beg > buf && beg[-1] != eol)	    continue;	  if (beg + len < buf + size && beg[len] != eol)	    continue;	  goto success;	}      else if (match_words)	for (try = beg; len; )	  {	    if (try > buf && WCHAR((unsigned char) try[-1]))	      break;	    if (try + len < buf + size && WCHAR((unsigned char) try[len]))	      {		offset = kwsexec (kwset, beg, --len, &kwsmatch);		if (offset == (size_t) -1)		  {#ifdef MBS_SUPPORT		    if (MB_CUR_MAX > 1)		      free (mb_properties);#endif /* MBS_SUPPORT */		    return offset;		  }		try = beg + offset;		len = kwsmatch.size[0];	      }	    else	      goto success;	  }      else	goto success;    }#ifdef MBS_SUPPORT  if (MB_CUR_MAX > 1)    free (mb_properties);#endif /* MBS_SUPPORT */  return -1; success:  end = memchr (beg + len, eol, (buf + size) - (beg + len));  end++;  while (buf < beg && beg[-1] != eol)    --beg;  *match_size = end - beg;#ifdef MBS_SUPPORT  if (MB_CUR_MAX > 1)    free (mb_properties);#endif /* MBS_SUPPORT */  return beg - buf;}#if HAVE_LIBPCRE/* Compiled internal form of a Perl regular expression.  */static pcre *cre;/* Additional information about the pattern.  */static pcre_extra *extra;#endifstatic voidPcompile (char const *pattern, size_t size){#if !HAVE_LIBPCRE  error (2, 0, _("The -P option is not supported"));#else  int e;  char const *ep;  char *re = xmalloc (4 * size + 7);  int flags = PCRE_MULTILINE | (match_icase ? PCRE_CASELESS : 0);  char const *patlim = pattern + size;  char *n = re;  char const *p;  char const *pnul;  /* FIXME: Remove this restriction.  */  if (eolbyte != '\n')    error (2, 0, _("The -P and -z options cannot be combined"));  *n = '\0';  if (match_lines)    strcpy (n, "^(");  if (match_words)    strcpy (n, "\\b(");  n += strlen (n);  /* The PCRE interface doesn't allow NUL bytes in the pattern, so     replace each NUL byte in the pattern with the four characters     "\000", removing a preceding backslash if there are an odd     number of backslashes before the NUL.     FIXME: This method does not work with some multibyte character     encodings, notably Shift-JIS, where a multibyte character can end     in a backslash byte.  */  for (p = pattern; (pnul = memchr (p, '\0', patlim - p)); p = pnul + 1)    {      memcpy (n, p, pnul - p);      n += pnul - p;      for (p = pnul; pattern < p && p[-1] == '\\'; p--)	continue;      n -= (pnul - p) & 1;      strcpy (n, "\\000");      n += 4;    }  memcpy (n, p, patlim - p);  n += patlim - p;  *n = '\0';  if (match_words)    strcpy (n, ")\\b");  if (match_lines)    strcpy (n, ")$");  cre = pcre_compile (re, flags, &ep, &e, pcre_maketables ());  if (!cre)    error (2, 0, ep);  extra = pcre_study (cre, 0, &ep);  if (ep)    error (2, 0, ep);  free (re);#endif}static size_tPexecute (char const *buf, size_t size, size_t *match_size, int exact){#if !HAVE_LIBPCRE  abort ();  return -1;#else  /* This array must have at least two elements; everything after that     is just for performance improvement in pcre_exec.  */  int sub[300];  int e = pcre_exec (cre, extra, buf, size, 0, 0,		     sub, sizeof sub / sizeof *sub);  if (e <= 0)    {      switch (e)	{	case PCRE_ERROR_NOMATCH:	  return -1;	case PCRE_ERROR_NOMEMORY:	  error (2, 0, _("Memory exhausted"));	default:	  abort ();	}    }  else    {      /* Narrow down to the line we've found.  */      char const *beg = buf + sub[0];      char const *end = buf + sub[1];      char const *buflim = buf + size;      char eol = eolbyte;      if (!exact)	{	  end = memchr (end, eol, buflim - end);	  end++;	  while (buf < beg && beg[-1] != eol)	    --beg;	}      *match_size = end - beg;      return beg - buf;    }#endif}struct matcher const matchers[] = {  { "default", Gcompile, EGexecute },  { "grep", Gcompile, EGexecute },  { "egrep", Ecompile, EGexecute },  { "awk", Ecompile, EGexecute },  { "fgrep", Fcompile, Fexecute },  { "perl", Pcompile, Pexecute },  { "", 0, 0 },};

⌨️ 快捷键说明

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