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

📄 mined2.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
  		do {  			subs++;	/* Increment subs */  			if ((textp = substitute(line, program,replacement))								     == NIL_PTR)  				return;	/* Line too long */  		} while ((program->status & BEGIN_LINE) != BEGIN_LINE &&			 (program->status & END_LINE) != END_LINE &&					  line_check(program, textp, FORWARD));  		/* Check to see if we can print the result */  		if (page <= screenmax) {  			set_cursor(0, page);  			line_print(line);  		}  	}  	if (page <= screenmax)  		page++;  	line = line->next;  } while (line != tail && file == VALID && quit == FALSE);  copy_string(mess_buf, (quit == TRUE) ? "(Aborted) " : "");/* Fix the status line */  if (subs == 0L && quit == FALSE)  	error("Pattern not found.", NIL_PTR);  else if (lines >= REPORT || quit == TRUE) {  	build_string(mess_buf, "%s %D substitutions on %D lines.", mess_buf,								   subs, lines);  	status_line(mess_buf, NIL_PTR);  }  else if (file == NOT_VALID && subs >= REPORT)  	status_line(num_out(subs), " substitutions.");  else  	clear_status();  move_to (x, y);}/* * Substitute() replaces the match on this line by the substitute pattern * as indicated by the program. Every '&' in the replacement is replaced by  * the original match. A \ in the replacement escapes the next character. */char *substitute(line, program, replacement)LINE *line;REGEX *program;char *replacement;		/* Contains replacement pattern */{  register char *textp = text_buffer;  register char *subp = replacement;  char *linep = line->text;  char *amp;  modified = TRUE;/* Copy part of line until the beginning of the match */  while (linep != program->start_ptr)  	*textp++ = *linep++;  /* * Replace the match by the substitution pattern. Each occurrence of '&' is * replaced by the original match. A \ escapes the next character. */  while (*subp != '\0' && textp < &text_buffer[MAX_CHARS]) {  	if (*subp == '&') {		/* Replace the original match */  		amp = program->start_ptr;  		while (amp < program->end_ptr && textp<&text_buffer[MAX_CHARS])  			*textp++ = *amp++;  		subp++;  	}  	else {  		if (*subp == '\\' && *(subp + 1) != '\0')  			subp++;  		*textp++ = *subp++;  	}  }/* Check for line length not exceeding MAX_CHARS */  if (length_of(text_buffer) + length_of(program->end_ptr) >= MAX_CHARS) {  	error("Substitution result: line too big", NIL_PTR);  	return NIL_PTR;  }/* Append last part of line to the new build line */  copy_string(textp, program->end_ptr);/* Free old line and install new one */  free_space(line->text);  line->text = alloc(length_of(text_buffer) + 1);  copy_string(line->text, text_buffer);  return(line->text + (textp - text_buffer));}/* * Search() calls get_expression to fetch the expression. If this went well, * the function match() is called which returns the line with the next match. * If this line is the NIL_LINE, it means that a match could not be found. * Find_x() and find_y() display the right page on the screen, and return * the right coordinates for x and y. These coordinates are passed to move_to() */void search(message, method)char *message;FLAG method;{  register REGEX *program;  register LINE *match_line;/* Get the expression */  if ((program = get_expression(message)) == NIL_REG)  	return;  set_cursor(0, ymax);  flush();/* Find the match */  if ((match_line = match(program, cur_text, method)) == NIL_LINE) {  	if (quit == TRUE)  		status_line("Aborted", NIL_PTR);  	else  		status_line("Pattern not found.", NIL_PTR);  	return;  }  move(0, program->start_ptr, find_y(match_line));  clear_status();}/* * find_y() checks if the matched line is on the current page.  If it is, it * returns the new y coordinate, else it displays the correct page with the * matched line in the middle and returns the new y value; */int find_y(match_line)LINE *match_line;{  register LINE *line;  register int count = 0;/* Check if match_line is on the same page as currently displayed. */  for (line = top_line; line != match_line && line != bot_line->next;  						      line = line->next)  	count++;  if (line != bot_line->next)  	return count;/* Display new page, with match_line in center. */  if ((line = proceed(match_line, -(screenmax >> 1))) == header) {  /* Can't display in the middle. Make first line of file top_line */  	count = 0;  	for (line = header->next; line != match_line; line = line->next)  		count++;  	line = header->next;  }  else	/* New page is displayed. Set cursor to middle of page */  	count = screenmax >> 1;/* Reset pointers and redraw the screen */  reset(line, 0);  RD();  return count;}/* Opcodes for characters */#define	NORMAL		0x0200#define DOT		0x0400#define EOLN		0x0800#define STAR		0x1000#define BRACKET		0x2000#define NEGATE		0x0100#define DONE		0x4000/* Mask for opcodes and characters */#define LOW_BYTE	0x00FF#define HIGH_BYTE	0xFF00/* Previous is the contents of the previous address (ptr) points to */#define previous(ptr)		(*((ptr) - 1))/* Buffer to store outcome of compilation */int exp_buffer[BLOCK_SIZE];/* Errors often used */char *too_long = "Regular expression too long";/* * Reg_error() is called by compile() is something went wrong. It set the * status of the structure to error, and assigns the error field of the union. */#define reg_error(str)	program->status = REG_ERROR, \  					program->result.err_mess = (str)/* * Finished() is called when everything went right during compilation. It * allocates space for the expression, and copies the expression buffer into * this field. */void finished(program, last_exp)register REGEX *program;int *last_exp;{  register int length = (last_exp - exp_buffer) * sizeof(int);/* Allocate space */  program->result.expression = (int *) alloc(length);/* Copy expression. (expression consists of ints!) */  bcopy(exp_buffer, program->result.expression, length);}/* * Compile compiles the pattern into a more comprehensible form and returns a  * REGEX structure. If something went wrong, the status field of the structure * is set to REG_ERROR and an error message is set into the err_mess field of * the union. If all went well the expression is saved and the expression * pointer is set to the saved (and compiled) expression. */void compile(pattern, program)register char *pattern;			/* Pointer to pattern */REGEX *program;{  register int *expression = exp_buffer;  int *prev_char;			/* Pointer to previous compiled atom */  int *acct_field;		/* Pointer to last BRACKET start */  FLAG negate;			/* Negate flag for BRACKET */  char low_char;			/* Index for chars in BRACKET */  char c;/* Check for begin of line */  if (*pattern == '^') {  	program->status = BEGIN_LINE;  	pattern++;  }  else {  	program->status = 0;/* If the first character is a '*' we have to assign it here. */  	if (*pattern == '*') {  		*expression++ = '*' + NORMAL;  		pattern++;  	}  }  for (; ;) {  	switch (c = *pattern++) {  	case '.' :  		*expression++ = DOT;  		break;  	case '$' :  		/*  		 * Only means EOLN if it is the last char of the pattern  		 */  		if (*pattern == '\0') {  			*expression++ = EOLN | DONE;  			program->status |= END_LINE;  			finished(program, expression);  			return;  		}  		else  			*expression++ = NORMAL + '$';  		break;  	case '\0' :  		*expression++ = DONE;  		finished(program, expression);  		return;  	case '\\' :  		/* If last char, it must! mean a normal '\' */  		if (*pattern == '\0')  			*expression++ = NORMAL + '\\';  		else  			*expression++ = NORMAL + *pattern++;  		break;  	case '*' :  		/*  		 * If the previous expression was a [] find out the  		 * begin of the list, and adjust the opcode.  		 */  		prev_char = expression - 1;  		if (*prev_char & BRACKET)  			*(expression - (*acct_field & LOW_BYTE))|= STAR;  		else  			*prev_char |= STAR;  		break;  	case '[' :  		/*  		 * First field in expression gives information about  		 * the list.  		 * The opcode consists of BRACKET and if necessary  		 * NEGATE to indicate that the list should be negated  		 * and/or STAR to indicate a number of sequence of this   		 * list.  		 * The lower byte contains the length of the list.  		 */  		acct_field = expression++;  		if (*pattern == '^') {	/* List must be negated */  			pattern++;  			negate = TRUE;  		}  		else  			negate = FALSE;  		while (*pattern != ']') {  			if (*pattern == '\0') {  				reg_error("Missing ]");  				return;  			}  			if (*pattern == '\\')  				pattern++;  			*expression++ = *pattern++;  			if (*pattern == '-') {  						/* Make list of chars */  				low_char = previous(pattern);  				pattern++;	/* Skip '-' */  				if (low_char++ > *pattern) {  					reg_error("Bad range in [a-z]");  					return;  				}  				/* Build list */  				while (low_char <= *pattern)  					*expression++ = low_char++;  				pattern++;  			}  			if (expression >= &exp_buffer[BLOCK_SIZE]) {  				reg_error(too_long);  				return;  			}  		}  		pattern++;			/* Skip ']' */  		/* Assign length of list in acct field */  		if ((*acct_field = (expression - acct_field)) == 1) {  			reg_error("Empty []");  			return;  		}  		/* Assign negate and bracket field */  		*acct_field |= BRACKET;  		if (negate == TRUE)  			*acct_field |= NEGATE;  		/*  		 * Add BRACKET to opcode of last char in field because  		 * a '*' may be following the list.  		 */  		previous(expression) |= BRACKET;  		break;  	default :  		*expression++ = c + NORMAL;  	}  	if (expression == &exp_buffer[BLOCK_SIZE]) {  		reg_error(too_long);  		return;  	}  }  /* NOTREACHED */}/* * Match gets as argument the program, pointer to place in current line to  * start from and the method to search for (either FORWARD or REVERSE). * Match() will look through the whole file until a match is found. * NIL_LINE is returned if no match could be found. */LINE *match(program, string, method)REGEX *program;char *string;register FLAG method;{  register LINE *line = cur_line;  char old_char;				/* For saving chars *//* Corrupted program */  if (program->status == REG_ERROR)  	return NIL_LINE;/* Check part of text first */  if (!(program->status & BEGIN_LINE)) {  	if (method == FORWARD) {  		if (line_check(program, string + 1, method) == MATCH)  			return cur_line;	/* Match found */  	}  	else if (!(program->status & END_LINE)) {  		old_char = *string;	/* Save char and */  		*string = '\n';		/* Assign '\n' for line_check */  		if (line_check(program, line->text, method) == MATCH) {  			*string = old_char; /* Restore char */  			return cur_line;    /* Found match */  		}  		*string = old_char;	/* No match, but restore char */  	}  }/* No match in last (or first) part of line. Check out rest of file */  do {  	line = (method == FORWARD) ? line->next : line->prev;  	if (line->text == NIL_PTR)	/* Header/tail */  		continue;  	if (line_check(program, line->text, method) == MATCH)  		return line;  } while (line != cur_line && quit == FALSE);/* No match found. */  return NIL_LINE;}/* * Line_check() checks the line (or rather string) for a match. Method * indicates FORWARD or REVERSE search. It scans through the whole string * until a match is found, or the end of the string is reached. */int line_check(program, string, method)register REGEX *program;char *string;FLAG method;{  register char *textp = string;/* Assign start_ptr field. We might find a match right away! */  program->start_ptr = textp;/* If the match must be anchored, just check the string. */  if (program->status & BEGIN_LINE)  	return check_string(program, string, NIL_INT);    if (method == REVERSE) {  	/* First move to the end of the string */  	for (textp = string; *textp != '\n'; textp++)  		;  	/* Start checking string until the begin of the string is met */  	while (textp >= string) {  		program->start_ptr = textp;  		if (check_string(program, textp--, NIL_INT))  			return MATCH;  	}  }  else {  	/* Move through the string until the end of is found */	while (quit == FALSE && *textp != '\0') {  		program->start_ptr = textp;  		if (check_string(program, textp, NIL_INT))  			return MATCH;		if (*textp == '\n')			break;		textp++;  	}  }  return NO_MATCH;}/* * Check() checks of a match can be found in the given string. Whenever a STAR * is found during matching, then the begin position of the string is marked * and the maximum number of matches is performed. Then the function star() * is called which starts to finish the match from this position of the string * (and expression). Check() return MATCH for a match, NO_MATCH is the string  * couldn't be matched or REG_ERROR for an illegal opcode in expression. */int check_string(program, string, expression)REGEX *program;register char *string;int *expression;{  register int opcode;		/* Holds opcode of next expr. atom */  char c;				/* Char that must be matched */  char *mark;			/* For marking position */  int star_fl;			/* A star has been born */  if (expression == NIL_INT)  	expression = program->result.expression;/* Loop until end of string or end of expression */  while (quit == FALSE && !(*expression & DONE) &&					   *string != '\0' && *string != '\n') {  	c = *expression & LOW_BYTE;	  /* Extract match char */  	opcode = *expression & HIGH_BYTE; /* Extract opcode */  	if (star_fl = (opcode & STAR)) {  /* Check star occurrence */  		opcode &= ~STAR;	  /* Strip opcode */  		mark = string;		  /* Mark current position */  	}  	expression++;		/* Increment expr. */  	switch (opcode) {  	case NORMAL :  		if (star_fl)  			while (*string++ == c)	/* Skip all matches */  				;  		else if (*string++ != c)  			return NO_MATCH;  		break;  	case DOT :  		string++;  		if (star_fl)			/* Skip to eoln */  			while (*string != '\0' && *string++ != '\n')  				;  		break;  	case NEGATE | BRACKET:  	case BRACKET :  		if (star_fl)  			while (in_list(expression, *string++, c, opcode)								       == MATCH)  				;  		else if (in_list(expression, *string++, c, opcode) == NO_MATCH)  			return NO_MATCH;  		expression += c - 1;	/* Add length of list */  		break;  	default :  		panic("Corrupted program in check_string()");  	}  	if (star_fl)   		return star(program, mark, string, expression);  }  if (*expression & DONE) {  	program->end_ptr = string;	/* Match ends here */  	/*  	 * We might have found a match. The last thing to do is check  	 * whether a '$' was given at the end of the expression, or  	 * the match was found on a null string. (E.g. [a-z]* always  	 * matches) unless a ^ or $ was included in the pattern.  	 */  	if ((*expression & EOLN) && *string != '\n' && *string != '\0')  		return NO_MATCH;	if (string == program->start_ptr && !(program->status & BEGIN_LINE)					 && !(*expression & EOLN))  		return NO_MATCH;  	return MATCH;  }  return NO_MATCH;}/* * Star() calls check_string() to find out the longest match possible. * It searches backwards until the (in check_string()) marked position * is reached, or a match is found. */int star(program, end_position, string, expression)REGEX *program;register char *end_position;register char *string;int *expression;{  do {  	string--;  	if (check_string(program, string, expression))  		return MATCH;  } while (string != end_position);  return NO_MATCH;}/* * In_list() checks if the given character is in the list of []. If it is * it returns MATCH. if it isn't it returns NO_MATCH. These returns values * are reversed when the NEGATE field in the opcode is present. */int in_list(list, c, list_length, opcode)register int *list;char c;register int list_length;int opcode;{  if (c == '\0' || c == '\n')	/* End of string, never matches */  	return NO_MATCH;  while (list_length-- > 1) {	/* > 1, don't check acct_field */  	if ((*list & LOW_BYTE) == c)  		return (opcode & NEGATE) ? NO_MATCH : MATCH;  	list++;  }  return (opcode & NEGATE) ? MATCH : NO_MATCH;}/* * Dummy_line() adds an empty line at the end of the file. This is sometimes * useful in combination with the EF and DN command in combination with the * Yank command set. */void dummy_line(){	(void) line_insert(tail->prev, "\n", 1);	tail->prev->shift_count = DUMMY;	if (last_y != screenmax) {		last_y++;		bot_line = bot_line->next;	}}

⌨️ 快捷键说明

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