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

📄 search.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* String search routines for GNU Emacs.   Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.This file is part of GNU Emacs.GNU Emacs is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU Emacs is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Emacs; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */#include "config.h"#include "lisp.h"#include "syntax.h"#include "buffer.h"#include "commands.h"#include "regex.h"#define max(a, b) ((a) > (b) ? (a) : (b))#define min(a, b) ((a) < (b) ? (a) : (b))unsigned char downcase_table[01000] = {0};	/* folds upper to lower case */	      /* A WHEEL WILL FALL OFF IF, IN A trt, CHARACTER A */	      /* TRANSLATES INTO CHARACTER B AND CHARACTER B DOES NOT */	      /* ALSO TRANSLATE INTO CHARACTER B. */ /* If that constraint is met, compute_trt_inverse will follow a */ /* translation table with its inverse.  The inverse of a table */ /* follows the table at table[0400].  The form of this is that if */ /* table[a]=b then the chain starting at table[0400+b], linked by */ /* link(x)=table[0400+x] and ended by b must include a. *//* At present compute_trt_inverse is blinded and the inverse for this */ /* particular table is created by a single-purpose loop. */ /* compute_trt_inverse has been tested on the following cases: */ /* trt[x]=x, trt[x]=(+ 3 (logand x, 0370)), trt[x]='a', and the */ /* downcase table. *//* We compile regexps into this buffer and then use it for searching. */struct re_pattern_buffer searchbuf;char search_fastmap[0400];/* Last regexp we compiled */Lisp_Object last_regexp;/* Every call to re_match, etc., must pass &search_regs as the regs argument unless you can show it is unnecessary (i.e., if re_match is certainly going to be called again before region-around-match can be called).  */static struct re_registers search_regs;/* error condition signalled when regexp compile_pattern fails */Lisp_Object Qinvalid_regexp;/* Compile a regexp and signal a Lisp error if anything goes wrong.  */compile_pattern (pattern, bufp, translate)     Lisp_Object pattern;     struct re_pattern_buffer *bufp;     char *translate;{  char *val;  Lisp_Object dummy;  if (EQ (pattern, last_regexp)      && translate == bufp->translate)    return;  last_regexp = Qnil;  bufp->translate = translate;  val = re_compile_pattern (XSTRING (pattern)->data,			    XSTRING (pattern)->size,			    bufp);  if (val)    {      dummy = build_string (val);      while (1)	Fsignal (Qinvalid_regexp, Fcons (dummy, Qnil));    }  last_regexp = pattern;  return;}/* Error condition used for failing searches */Lisp_Object Qsearch_failed;Lisp_Objectsignal_failure (arg)     Lisp_Object arg;{  Fsignal (Qsearch_failed, Fcons (arg, Qnil));  return Qnil;}DEFUN ("looking-at", Flooking_at, Slooking_at, 1, 1, 0,  "t if text after point matches regular expression PAT.")  (string)     Lisp_Object string;{  Lisp_Object val;  unsigned char *p1, *p2;  int s1, s2;  register int i;  CHECK_STRING (string, 0);  compile_pattern (string, &searchbuf,		   !NULL (current_buffer->case_fold_search) ? (char *) downcase_table : 0);  immediate_quit = 1;  QUIT;			/* Do a pending quit right away, to avoid paradoxical behavior */  /* Get pointers and sizes of the two strings     that make up the visible portion of the buffer. */  p1 = BEGV_ADDR;  s1 = GPT - BEGV;  p2 = GAP_END_ADDR;  s2 = ZV - GPT;  if (s1 < 0)    {      p2 = p1;      s2 = ZV - BEGV;      s1 = 0;    }  if (s2 < 0)    {      s1 = ZV - BEGV;      s2 = 0;    }    val = (0 <= re_match_2 (&searchbuf, p1, s1, p2, s2,			  point - BEGV, &search_regs, ZV - BEGV)	 ? Qt : Qnil);  for (i = 0; i < RE_NREGS; i++)    if (search_regs.start[i] >= 0)      {	search_regs.start[i] += BEGV;	search_regs.end[i] += BEGV;      }  immediate_quit = 0;  return val;}DEFUN ("string-match", Fstring_match, Sstring_match, 2, 3, 0,  "Return index of start of first match for REGEXP in STRING, or nil.\n\If third arg START is non-nil, start search at that index in STRING.\n\For index of first char beyond the match, do (match-end 0).\n\match-end and match-beginning also give indices of substrings\n\matched by parenthesis constructs in the pattern.")  (regexp, string, start)     Lisp_Object regexp, string, start;{  int val;  int s;  CHECK_STRING (regexp, 0);  CHECK_STRING (string, 1);  if (NULL (start))    s = 0;  else    {      int len = XSTRING (string)->size;      CHECK_NUMBER (start, 2);      s = XINT (start);      if (s < 0 && -s <= len)	s = len - s;      else if (0 > s || s > len)	args_out_of_range (string, start);    }  compile_pattern (regexp, &searchbuf,		   !NULL (current_buffer->case_fold_search) ? (char *) downcase_table : 0);  immediate_quit = 1;  val = re_search (&searchbuf, XSTRING (string)->data, XSTRING (string)->size,			       s, XSTRING (string)->size - s, &search_regs);  immediate_quit = 0;  if (val < 0) return Qnil;  return make_number (val);}scan_buffer (target, pos, cnt, shortage)     int *shortage, pos;     register int cnt, target;{  int lim = ((cnt > 0) ? ZV - 1 : BEGV);  int direction = ((cnt > 0) ? 1 : -1);  register int lim0;  unsigned char *base;  register unsigned char *cursor, *limit;  if (shortage != 0)    *shortage = 0;  immediate_quit = 1;  if (cnt > 0)    while (pos != lim + 1)      {	lim0 =  BufferSafeCeiling (pos);	lim0 = min (lim, lim0);	limit = &FETCH_CHAR (lim0) + 1;	base = (cursor = &FETCH_CHAR (pos));	while (1)	  {	    while (*cursor != target && ++cursor != limit)	      ;	    if (cursor != limit)	      {		if (--cnt == 0)		  {		    immediate_quit = 0;		    return (pos + cursor - base + 1);		  }		else		  if (++cursor == limit)		    break;	      }	    else	      break;	  }	pos += cursor - base;      }  else    {      pos--;			/* first character we scan */      while (pos > lim - 1)	{			/* we WILL scan under pos */	  lim0 =  BufferSafeFloor (pos);	  lim0 = max (lim, lim0);	  limit = &FETCH_CHAR (lim0) - 1;	  base = (cursor = &FETCH_CHAR (pos));	  cursor++;	  while (1)	    {	      while (--cursor != limit && *cursor != target)		;	      if (cursor != limit)		{		  if (++cnt == 0)		    {		      immediate_quit = 0;		      return (pos + cursor - base + 1);		    }		}	      else		break;	    }	  pos += cursor - base;	}    }  immediate_quit = 0;  if (shortage != 0)    *shortage = cnt * direction;  return (pos + ((direction == 1 ? 0 : 1)));}intfind_next_newline (from, cnt)     register int from, cnt;{  return (scan_buffer ('\n', from, cnt, (int *) 0));}DEFUN ("skip-chars-forward", Fskip_chars_forward, Sskip_chars_forward, 1, 2, 0,  "Move point forward, stopping before a char not in CHARS, or at position LIM.\n\CHARS is like the inside of a [...] in a regular expression\n\except that ] is never special and \\ quotes ^, - or \\.\n\Thus, with arg \"a-zA-Z\", this skips letters stopping before first nonletter.\n\With arg \"^a-zA-Z\", skips nonletters stopping before first letter.")  (string, lim)     Lisp_Object string, lim;{  skip_chars (1, string, lim);  return Qnil;}DEFUN ("skip-chars-backward", Fskip_chars_backward, Sskip_chars_backward, 1, 2, 0,  "Move point backward, stopping after a char not in CHARS, or at position LIM.\n\See skip-chars-forward for details.")  (string, lim)     Lisp_Object string, lim;{  skip_chars (0, string, lim);  return Qnil;}skip_chars (forwardp, string, lim)     int forwardp;     Lisp_Object string, lim;{  register unsigned char *p, *pend;  register unsigned char c;  unsigned char fastmap[0400];  int negate = 0;  register int i;  CHECK_STRING (string, 0);  if (NULL (lim))    XFASTINT (lim) = forwardp ? ZV : BEGV;  else    CHECK_NUMBER_COERCE_MARKER (lim, 1);  /* In any case, don't allow scan outside bounds of buffer.  */  if (XFASTINT (lim) > ZV)    XFASTINT (lim) = ZV;  if (XFASTINT (lim) < BEGV)    XFASTINT (lim) = BEGV;  p = XSTRING (string)->data;  pend = p + XSTRING (string)->size;  bzero (fastmap, sizeof fastmap);  if (p != pend && *p == '^')    {      negate = 1; p++;    }  /* Find the characters specified and set their elements of fastmap.  */  while (p != pend)    {      c = *p++;      if (c == '\\')        {	  if (p == pend) break;	  c = *p++;	}      if (p != pend && *p == '-')	{	  p++;	  if (p == pend) break;	  while (c <= *p)	    {	      fastmap[c] = 1;	      c++;	    }	  p++;	}      else	fastmap[c] = 1;    }  /* If ^ was the first character, complement the fastmap. */  if (negate)    for (i = 0; i < sizeof fastmap; i++)      fastmap[i] ^= 1;  immediate_quit = 1;  if (forwardp)    {      while (point < XINT (lim) && fastmap[FETCH_CHAR (point)])	SET_PT (point + 1);    }  else    {      while (point > XINT (lim) && fastmap[FETCH_CHAR (point - 1)])	SET_PT (point - 1);    }  immediate_quit = 0;}/* Subroutines of Lisp buffer search functions. */static Lisp_Objectsearch_command (string, bound, noerror, count, direction, RE)     Lisp_Object string, bound, noerror, count;     int direction;     int RE;{  register int np;  int lim;  int n = direction;  if (!NULL (count))    {      CHECK_NUMBER (count, 3);      n *= XINT (count);    }  CHECK_STRING (string, 0);  if (NULL (bound))    lim = n > 0 ? ZV : BEGV;  else    {      CHECK_NUMBER_COERCE_MARKER (bound, 1);      lim = XINT (bound);      if (n > 0 ? lim < point : lim > point)	error ("Invalid search bound (wrong side of point)");      if (lim > ZV)	lim = ZV;      if (lim < BEGV)	lim = BEGV;    }  np = search_buffer (string, point, lim, n, RE,		      !NULL (current_buffer->case_fold_search) ? downcase_table : 0);  if (np <= 0)    {      if (NULL (noerror))	return signal_failure (string);      if (!EQ (noerror, Qt))	{	  if (lim < BEGV || lim > ZV)	    abort ();	  SET_PT (lim);	}      return Qnil;    }  if (np < BEGV || np > ZV)    abort ();  SET_PT (np);  return Qt;}/* search for the n'th occurrence of `string' in the current buffer,   starting at position `from' and stopping at position `lim',   treating `pat' as a literal string if `RE' is false or as   a regular expression if `RE' is true.   If `n' is positive, searching is forward and `lim' must be greater than `from'.

⌨️ 快捷键说明

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