xref: /original-bsd/contrib/ed/search.c (revision d9657196)
1 /*-
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rodney Ruddock of the University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)search.c	5.3 (Berkeley) 02/28/93";
13 #endif /* not lint */
14 
15 #include <sys/types.h>
16 
17 #include <regex.h>
18 #include <setjmp.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #ifdef DBI
24 #include <db.h>
25 #endif
26 
27 #include "ed.h"
28 #include "extern.h"
29 
30 /*
31  * searches forward through the buffer (wrapping if necessary) for a
32  * line that contains a match to the RE.
33  */
34 
35 LINE *
36 search(inputt, errnum)
37 	FILE *inputt;
38 	int *errnum;
39 {
40 	LINE *l_temp;
41 	int l_err;
42 	char *l_patt;
43 
44 	if (current)
45 		l_temp = current->below;
46 	else {
47 		*errnum = -1;
48 		ungetc(ss, inputt);
49 		strcpy(help_msg, "buffer empty");
50 		return(NULL);
51 	}
52 	/* Get the RE. */
53 	l_patt = get_pattern(ss, inputt, errnum, 0);
54 	if (*errnum < -1)
55 		return (NULL);
56 	*errnum = 0;
57 	if ((RE_flag == 0) && (l_patt[1] == '\0')) {
58 		*errnum = -1;
59 		ungetc(ss, inputt);
60 		return (NULL);
61 	} else
62 		if (l_patt[1] || (RE_patt == NULL)) {
63 			sigspecial++;
64 			free(RE_patt);
65 			RE_patt = l_patt;
66 			sigspecial--;
67 			if (sigint_flag && (!sigspecial))
68 				SIGINT_ACTION;
69 		}
70 	RE_sol = (RE_patt[1] == '^') ? 1 : 0;
71 
72 	/* Compile it up. */
73 	if ((l_patt[1]) &&
74 	    (regfree(&RE_comp), l_err = regcomp(&RE_comp, &RE_patt[1], 0))) {
75 		regerror(l_err, &RE_comp, help_msg, 128);
76 		*errnum = -1;
77 		RE_flag = 0;
78 		ungetc(ss, inputt);
79 		return (NULL);
80 	}
81 	RE_flag = 1;
82 
83 	/* Find a line that has the RE in it. */
84 	for (;;) {		/* (l_temp != current) */
85 		if (l_temp == NULL) {
86 			if (top != NULL)
87 				l_temp = top;
88 			else
89 				break;
90 		}
91 		get_line(l_temp->handle, l_temp->len);
92 		if (sigint_flag && (!sigspecial))
93 			SIGINT_ACTION;
94 		if (regexec(&RE_comp, text, (size_t) RE_SEC, RE_match, 0)) {
95 			l_temp = l_temp->below;
96 			if (l_temp == (current->below))
97 				break;
98 		} else {
99 			*errnum = 0;
100 			return (l_temp);
101 		}
102 	}
103 	strcpy(help_msg, "RE not found");
104 	*errnum = -1;
105 	return (NULL);
106 }
107 
108 /*
109  * Searches backward through the buffer (wrapping if necessary) to find
110  * a line that contains a match to the RE.
111  */
112 LINE *
113 search_r(inputt, errnum)
114 	FILE *inputt;
115 	int *errnum;
116 {
117 	LINE *l_temp;
118 	int l_err;
119 	char *l_patt;
120 
121 	if (current)
122 		l_temp = current->above;
123 	else {
124 		*errnum = -1;
125 		ungetc(ss, inputt);
126 		strcpy(help_msg, "buffer empty");
127 		return(NULL);
128 	}
129 
130 	/* Get the RE. */
131 	l_patt = get_pattern(ss, inputt, errnum, 0);
132 	if (*errnum < -1)
133 		return (NULL);
134 	*errnum = 0;
135 	if ((RE_flag == 0) && (l_patt[1] == '\0')) {
136 		*errnum = -1;
137 		ungetc(ss, inputt);
138 		return (NULL);
139 	} else
140 		if (l_patt[1] || (RE_patt == NULL)) {
141 			sigspecial++;
142 			free(RE_patt);
143 			RE_patt = l_patt;
144 			sigspecial--;
145 			if (sigint_flag && (!sigspecial))
146 				SIGINT_ACTION;
147 		}
148 	RE_sol = (RE_patt[1] == '^') ? 1 : 0;
149 
150 	/* Compile up the RE. */
151 	if ((l_patt[1]) &&
152 	    (regfree(&RE_comp), l_err = regcomp(&RE_comp, &RE_patt[1], 0))) {
153 		regerror(l_err, &RE_comp, help_msg, 128);
154 		*errnum = -1;
155 		RE_flag = 0;
156 		ungetc(ss, inputt);
157 		return (NULL);
158 	}
159 	RE_flag = 1;
160 
161 	/* Search for a line that has the RE in it. */
162 	for (;;) {		/* (l_temp != (current->above)) */
163 		if (l_temp == NULL) {
164 			if (bottom != NULL)
165 				l_temp = bottom;
166 			else
167 				break;
168 		}
169 		get_line(l_temp->handle, l_temp->len);
170 		if (sigint_flag && (!sigspecial))
171 			SIGINT_ACTION;
172 		if (regexec(&RE_comp, text, (size_t) RE_SEC, RE_match, 0)) {
173 			l_temp = l_temp->above;
174 			if (l_temp == (current->above))
175 				break;
176 		} else {
177 			*errnum = 0;
178 			return (l_temp);
179 		}
180 	}
181 	strcpy(help_msg, "RE not found");
182 	*errnum = -1;
183 	return (NULL);
184 }
185