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

📄 search.c

📁 早期freebsd实现
💻 C
字号:
/* * Routines to search a file for a pattern. */#include "less.h"#include "position.h"#if REGCOMP#include "regexp.h"#endifextern int sigs;extern int how_search;extern int caseless;extern int linenums;extern int jump_sline;/* * Search for the n-th occurrence of a specified pattern,  * either forward or backward. * Return the number of matches not yet found in this file * (that is, n minus the number of matches found). * Return -1 if the search should be aborted. * Caller may continue the search in another file  * if less than n matches are found in this file. */	public intsearch(search_type, pattern, n)	int search_type;	char *pattern;	int n;{	POSITION pos, linepos, oldpos;	register char *p;	register char *q;	register int goforw;	register int want_match;	char *line;	int linenum;	int line_match;	static int is_caseless;#if RECOMP	char *re_comp();	PARG parg;#else#if REGCMP	char *regcmp();	static char *cpattern = NULL;#else#if REGCOMP	static struct regexp *regpattern = NULL;#else	static char lpbuf[100];	static char *last_pattern = NULL;#endif#endif#endif	/*	 * Extract flags and type of search.	 */	goforw = (SRCH_DIR(search_type) == SRCH_FORW);	want_match = !(search_type & SRCH_NOMATCH);	if (pattern != NULL && *pattern != '\0' && (is_caseless = caseless))	{		/*		 * Search will ignore case, unless		 * there are any uppercase letters in the pattern.		 */		for (p = pattern;  *p != '\0';  p++)			if (*p >= 'A' && *p <= 'Z')			{				is_caseless = 0;				break;			}	}#if RECOMP	/*	 * (re_comp handles a null pattern internally, 	 *  so there is no need to check for a null pattern here.)	 */	if ((parg.p_string = re_comp(pattern)) != NULL)	{		error("%s", &parg);		return (-1);	}#else#if REGCMP	if (pattern == NULL || *pattern == '\0')	{		/*		 * A null pattern means use the previous pattern.		 * The compiled previous pattern is in cpattern, so just use it.		 */		if (cpattern == NULL)		{			error("No previous regular expression", NULL_PARG);			return (-1);		}	} else	{		/*		 * Otherwise compile the given pattern.		 */		char *s;		if ((s = regcmp(pattern, 0)) == NULL)		{			error("Invalid pattern", NULL_PARG);			return (-1);		}		if (cpattern != NULL)			free(cpattern);		cpattern = s;	}#else#if REGCOMP	if (pattern == NULL || *pattern == '\0')	{		/*		 * A null pattern means use the previous pattern.		 * The compiled previous pattern is in regpattern, 		 * so just use it.		 */		if (regpattern == NULL)		{			error("No previous regular expression", NULL_PARG);			return (-1);		}	} else	{		/*		 * Otherwise compile the given pattern.		 */		struct regexp *s;		if ((s = regcomp(pattern)) == NULL)		{			error("Invalid pattern", NULL_PARG);			return (-1);		}		if (regpattern != NULL)			free(regpattern);		regpattern = s;	}#else	if (pattern == NULL || *pattern == '\0')	{		/*		 * Null pattern means use the previous pattern.		 */		if (last_pattern == NULL)		{			error("No previous regular expression", NULL_PARG);			return (-1);		}		pattern = last_pattern;	} else	{		strcpy(lpbuf, pattern);		last_pattern = lpbuf;	}#endif#endif#endif	/*	 * Figure out where to start the search.	 */	if (empty_screen())	{		/*		 * Start at the beginning (or end) of the file.		 * (The empty_screen() case is mainly for 		 * command line initiated searches;		 * for example, "+/xyz" on the command line.)		 */		if (goforw)			pos = ch_zero();		else 		{			pos = ch_length();			if (pos == NULL_POSITION)				pos = ch_zero();		}	} else 	{		if (how_search)		{			if (goforw)				linenum = BOTTOM_PLUS_ONE;			else				linenum = TOP;			pos = position(linenum);		} else		{			linenum = adjsline(jump_sline);			pos = position(linenum);			if (goforw)				pos = forw_raw_line(pos, (char **)NULL);		}	}	if (pos == NULL_POSITION)	{		/*		 * Can't find anyplace to start searching from.		 */		error("Nothing to search", NULL_PARG);		return (-1);	}	linenum = find_linenum(pos);	oldpos = pos;	for (;;)	{		/*		 * Get lines until we find a matching one or 		 * until we hit end-of-file (or beginning-of-file 		 * if we're going backwards).		 */		if (sigs)			/*			 * A signal aborts the search.			 */			return (-1);		if (goforw)		{			/*			 * Read the next line, and save the 			 * starting position of that line in linepos.			 */			linepos = pos;			pos = forw_raw_line(pos, &line);			if (linenum != 0)				linenum++;		} else		{			/*			 * Read the previous line and save the			 * starting position of that line in linepos.			 */			pos = back_raw_line(pos, &line);			linepos = pos;			if (linenum != 0)				linenum--;		}		if (pos == NULL_POSITION)		{			/*			 * We hit EOF/BOF without a match.			 */			return (n);		}		/*		 * If we're using line numbers, we might as well		 * remember the information we have now (the position		 * and line number of the current line).		 * Don't do it for every line because it slows down		 * the search.  Remember the line number only if		 * we're "far" from the last place we remembered it.		 */		if (linenums && abs(pos - oldpos) > 1024)		{			add_lnum(linenum, pos);			oldpos = pos;		}		if (is_caseless)		{			/*			 * If this is a caseless search, convert 			 * uppercase in the input line to lowercase.			 * While we're at it, remove any backspaces			 * along with the preceding char.			 * This allows us to match text which is 			 * underlined or overstruck.			 */			for (p = q = line;  *p != '\0';  p++, q++)			{				if (*p >= 'A' && *p <= 'Z')					/* Convert uppercase to lowercase. */					*q = *p + 'a' - 'A';				else if (q > line && *p == '\b')					/* Delete BS and preceding char. */					q -= 2;				else					/* Otherwise, just copy. */					*q = *p;			}		}		/*		 * Test the next line to see if we have a match.		 * This is done in a variety of ways, depending		 * on what pattern matching functions are available.		 */#if REGCMP		line_match = (regex(cpattern, line) != NULL);#else#if RECOMP		line_match = (re_exec(line) == 1);#else#if REGCOMP		line_match = regexec(regpattern, line);#else		line_match = match(pattern, line);#endif#endif#endif		/*		 * We are successful if want_match and line_match are		 * both true (want a match and got it),		 * or both false (want a non-match and got it).		 */		if (((want_match && line_match) || (!want_match && !line_match)) &&		      --n <= 0)			/*			 * Found the line.			 */			break;	}	jump_loc(linepos, jump_sline);	return (0);}#if (!REGCMP) && (!RECOMP) && (!REGCOMP)/* * We have neither regcmp() nor re_comp(). * We use this function to do simple pattern matching. * It supports no metacharacters like *, etc. */	static intmatch(pattern, buf)	char *pattern, *buf;{	register char *pp, *lp;	for ( ;  *buf != '\0';  buf++)	{		for (pp = pattern, lp = buf;  *pp == *lp;  pp++, lp++)			if (*pp == '\0' || *lp == '\0')				break;		if (*pp == '\0')			return (1);	}	return (0);}#endif

⌨️ 快捷键说明

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