xref: /csrg-svn/contrib/ed/search.c (revision 60663)
157700Sbostic /*-
2*60663Sbostic  * Copyright (c) 1992, 1993
3*60663Sbostic  *	The Regents of the University of California.  All rights reserved.
457700Sbostic  *
557700Sbostic  * This code is derived from software contributed to Berkeley by
657700Sbostic  * Rodney Ruddock of the University of Guelph.
757700Sbostic  *
857700Sbostic  * %sccs.include.redist.c%
957700Sbostic  */
1057700Sbostic 
1157700Sbostic #ifndef lint
12*60663Sbostic static char sccsid[] = "@(#)search.c	8.1 (Berkeley) 05/31/93";
1357700Sbostic #endif /* not lint */
1457700Sbostic 
1557710Sbostic #include <sys/types.h>
1657710Sbostic 
1757710Sbostic #include <regex.h>
1857710Sbostic #include <setjmp.h>
1957710Sbostic #include <stdio.h>
2057710Sbostic #include <stdlib.h>
2157710Sbostic #include <string.h>
2257710Sbostic 
2358315Sbostic #ifdef DBI
2458315Sbostic #include <db.h>
2558315Sbostic #endif
2658315Sbostic 
2757700Sbostic #include "ed.h"
2857710Sbostic #include "extern.h"
2957700Sbostic 
3057700Sbostic /*
3157700Sbostic  * searches forward through the buffer (wrapping if necessary) for a
3257700Sbostic  * line that contains a match to the RE.
3357700Sbostic  */
3457700Sbostic 
3557710Sbostic LINE *
search(inputt,errnum)3657710Sbostic search(inputt, errnum)
3757710Sbostic 	FILE *inputt;
3857710Sbostic 	int *errnum;
3957710Sbostic {
4057710Sbostic 	LINE *l_temp;
4157710Sbostic 	int l_err;
4257710Sbostic 	char *l_patt;
4357700Sbostic 
4458315Sbostic 	if (current)
4558315Sbostic 		l_temp = current->below;
4658315Sbostic 	else {
4758315Sbostic 		*errnum = -1;
4858315Sbostic 		ungetc(ss, inputt);
4958315Sbostic 		strcpy(help_msg, "buffer empty");
5058315Sbostic 		return(NULL);
5158315Sbostic 	}
5257710Sbostic 	/* Get the RE. */
5357710Sbostic 	l_patt = get_pattern(ss, inputt, errnum, 0);
5457710Sbostic 	if (*errnum < -1)
5557710Sbostic 		return (NULL);
5657710Sbostic 	*errnum = 0;
5757710Sbostic 	if ((RE_flag == 0) && (l_patt[1] == '\0')) {
5857710Sbostic 		*errnum = -1;
5957710Sbostic 		ungetc(ss, inputt);
6057710Sbostic 		return (NULL);
6157710Sbostic 	} else
6257710Sbostic 		if (l_patt[1] || (RE_patt == NULL)) {
6358315Sbostic 			sigspecial++;
6457710Sbostic 			free(RE_patt);
6557710Sbostic 			RE_patt = l_patt;
6658315Sbostic 			sigspecial--;
6758315Sbostic 			if (sigint_flag && (!sigspecial))
6858315Sbostic 				SIGINT_ACTION;
6957710Sbostic 		}
7057710Sbostic 	RE_sol = (RE_patt[1] == '^') ? 1 : 0;
7157700Sbostic 
7257710Sbostic 	/* Compile it up. */
7357710Sbostic 	if ((l_patt[1]) &&
7457710Sbostic 	    (regfree(&RE_comp), l_err = regcomp(&RE_comp, &RE_patt[1], 0))) {
7557710Sbostic 		regerror(l_err, &RE_comp, help_msg, 128);
7657710Sbostic 		*errnum = -1;
7757710Sbostic 		RE_flag = 0;
7857710Sbostic 		ungetc(ss, inputt);
7957710Sbostic 		return (NULL);
8057710Sbostic 	}
8157710Sbostic 	RE_flag = 1;
8257700Sbostic 
8357710Sbostic 	/* Find a line that has the RE in it. */
8457710Sbostic 	for (;;) {		/* (l_temp != current) */
8557710Sbostic 		if (l_temp == NULL) {
8657710Sbostic 			if (top != NULL)
8757710Sbostic 				l_temp = top;
8857710Sbostic 			else
8957710Sbostic 				break;
9057710Sbostic 		}
9157710Sbostic 		get_line(l_temp->handle, l_temp->len);
9258315Sbostic 		if (sigint_flag && (!sigspecial))
9358315Sbostic 			SIGINT_ACTION;
9457710Sbostic 		if (regexec(&RE_comp, text, (size_t) RE_SEC, RE_match, 0)) {
9557710Sbostic 			l_temp = l_temp->below;
9657710Sbostic 			if (l_temp == (current->below))
9757710Sbostic 				break;
9857710Sbostic 		} else {
9957710Sbostic 			*errnum = 0;
10057710Sbostic 			return (l_temp);
10157710Sbostic 		}
10257710Sbostic 	}
10357710Sbostic 	strcpy(help_msg, "RE not found");
10457710Sbostic 	*errnum = -1;
10557710Sbostic 	return (NULL);
10657710Sbostic }
10757700Sbostic 
10857700Sbostic /*
10957700Sbostic  * Searches backward through the buffer (wrapping if necessary) to find
11057700Sbostic  * a line that contains a match to the RE.
11157700Sbostic  */
11257710Sbostic LINE *
search_r(inputt,errnum)11357710Sbostic search_r(inputt, errnum)
11457710Sbostic 	FILE *inputt;
11557710Sbostic 	int *errnum;
11657710Sbostic {
11757710Sbostic 	LINE *l_temp;
11857710Sbostic 	int l_err;
11957710Sbostic 	char *l_patt;
12057700Sbostic 
12158315Sbostic 	if (current)
12258315Sbostic 		l_temp = current->above;
12358315Sbostic 	else {
12458315Sbostic 		*errnum = -1;
12558315Sbostic 		ungetc(ss, inputt);
12658315Sbostic 		strcpy(help_msg, "buffer empty");
12758315Sbostic 		return(NULL);
12858315Sbostic 	}
12957700Sbostic 
13057710Sbostic 	/* Get the RE. */
13157710Sbostic 	l_patt = get_pattern(ss, inputt, errnum, 0);
13257710Sbostic 	if (*errnum < -1)
13357710Sbostic 		return (NULL);
13457710Sbostic 	*errnum = 0;
13557710Sbostic 	if ((RE_flag == 0) && (l_patt[1] == '\0')) {
13657710Sbostic 		*errnum = -1;
13757710Sbostic 		ungetc(ss, inputt);
13857710Sbostic 		return (NULL);
13957710Sbostic 	} else
14057710Sbostic 		if (l_patt[1] || (RE_patt == NULL)) {
14158315Sbostic 			sigspecial++;
14257710Sbostic 			free(RE_patt);
14357710Sbostic 			RE_patt = l_patt;
14458315Sbostic 			sigspecial--;
14558315Sbostic 			if (sigint_flag && (!sigspecial))
14658315Sbostic 				SIGINT_ACTION;
14757710Sbostic 		}
14857710Sbostic 	RE_sol = (RE_patt[1] == '^') ? 1 : 0;
14957700Sbostic 
15057710Sbostic 	/* Compile up the RE. */
15157710Sbostic 	if ((l_patt[1]) &&
15257710Sbostic 	    (regfree(&RE_comp), l_err = regcomp(&RE_comp, &RE_patt[1], 0))) {
15357710Sbostic 		regerror(l_err, &RE_comp, help_msg, 128);
15457710Sbostic 		*errnum = -1;
15557710Sbostic 		RE_flag = 0;
15657710Sbostic 		ungetc(ss, inputt);
15757710Sbostic 		return (NULL);
15857710Sbostic 	}
15957710Sbostic 	RE_flag = 1;
16057700Sbostic 
16157710Sbostic 	/* Search for a line that has the RE in it. */
16257710Sbostic 	for (;;) {		/* (l_temp != (current->above)) */
16357710Sbostic 		if (l_temp == NULL) {
16457710Sbostic 			if (bottom != NULL)
16557710Sbostic 				l_temp = bottom;
16657710Sbostic 			else
16757710Sbostic 				break;
16857710Sbostic 		}
16957710Sbostic 		get_line(l_temp->handle, l_temp->len);
17058315Sbostic 		if (sigint_flag && (!sigspecial))
17158315Sbostic 			SIGINT_ACTION;
17257710Sbostic 		if (regexec(&RE_comp, text, (size_t) RE_SEC, RE_match, 0)) {
17357710Sbostic 			l_temp = l_temp->above;
17457710Sbostic 			if (l_temp == (current->above))
17557710Sbostic 				break;
17657710Sbostic 		} else {
17757710Sbostic 			*errnum = 0;
17857710Sbostic 			return (l_temp);
17957710Sbostic 		}
18057710Sbostic 	}
18157710Sbostic 	strcpy(help_msg, "RE not found");
18257710Sbostic 	*errnum = -1;
18357710Sbostic 	return (NULL);
18457710Sbostic }
185