xref: /openbsd-src/usr.bin/mg/grep.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: grep.c,v 1.1 2001/05/24 10:58:34 art Exp $	*/
2 /*
3  * Copyright (c) 2001 Artur Grabowski <art@openbsd.org>.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "def.h"
27 #include "kbd.h"
28 #include "funmap.h"
29 
30 static int	compile_goto_error(int f, int n);
31 static int	next_error(int f, int n);
32 static int	grep(int, int);
33 static int	compile(int, int);
34 static int	gid(int, int);
35 static BUFFER	*compile_mode(char *name, char *command);
36 
37 
38 void grep_init(void);
39 
40 /*
41  * Hints for next-error
42  *
43  * XXX - need some kind of callback to find out when those get killed.
44  */
45 MGWIN *compile_win;
46 BUFFER *compile_buffer;
47 
48 static PF compile_pf[] = {
49 	compile_goto_error,
50 };
51 
52 static struct KEYMAPE (1 + IMAPEXT) compilemap = {
53 	1,
54 	1 + IMAPEXT,
55 	rescan,
56 	{
57 		{ CCHR('M'), CCHR('M'), compile_pf, NULL },
58 	}
59 };
60 
61 void
62 grep_init(void)
63 {
64 	funmap_add(compile_goto_error, "compile-goto-error");
65 	funmap_add(next_error, "next-error");
66 	funmap_add(grep, "grep");
67 	funmap_add(compile, "compile");
68 	funmap_add(gid, "gid");
69 	maps_add((KEYMAP *)&compilemap, "compile");
70 }
71 
72 static int
73 grep(int f, int n)
74 {
75 	char command[NFILEN + 20];
76 	char prompt[NFILEN];
77 	BUFFER *bp;
78 	MGWIN *wp;
79 
80 	strcpy(prompt, "grep -n ");
81 	if (eread("Run grep: ", prompt, NFILEN, EFDEF|EFNEW|EFCR) == ABORT)
82 		return ABORT;
83 
84 	sprintf(command, "%s /dev/null", prompt);
85 
86 	if ((bp = compile_mode("*grep*", command)) == NULL)
87 		return FALSE;
88 	if ((wp = popbuf(bp)) == NULL)
89 		return FALSE;
90 	curbp = bp;
91 	compile_win = curwp = wp;
92 	return TRUE;
93 }
94 
95 static int
96 compile(int f, int n)
97 {
98 	char command[NFILEN + 20];
99 	char prompt[NFILEN];
100 	BUFFER *bp;
101 	MGWIN *wp;
102 
103 	strcpy(prompt, "make ");
104 	if (eread("Compile command: ", prompt, NFILEN, EFDEF|EFNEW|EFCR) == ABORT)
105 		return ABORT;
106 
107 	sprintf(command, "%s 2>&1", prompt);
108 
109 	if ((bp = compile_mode("*compile*", command)) == NULL)
110 		return FALSE;
111 	if ((wp = popbuf(bp)) == NULL)
112 		return FALSE;
113 	curbp = bp;
114 	compile_win = curwp = wp;
115 	return TRUE;
116 }
117 
118 /* id-utils foo. */
119 static int
120 gid(int f, int n)
121 {
122 	char command[NFILEN + 20];
123 	char prompt[NFILEN];
124 	BUFFER *bp;
125 	MGWIN *wp;
126 
127 	if (eread("Run gid (with args): ", prompt, NFILEN, EFNEW|EFCR) == ABORT)
128 		return ABORT;
129 
130 	sprintf(command, "gid %s", prompt);
131 
132 	if ((bp = compile_mode("*gid*", command)) == NULL)
133 		return FALSE;
134 	if ((wp = popbuf(bp)) == NULL)
135 		return FALSE;
136 	curbp = bp;
137 	compile_win = curwp = wp;
138 	return TRUE;
139 }
140 
141 BUFFER *
142 compile_mode(char *name, char *command)
143 {
144 	BUFFER *bp;
145 	FILE *pipe;
146 	char *buf;
147 	size_t len;
148 	int ret;
149 
150 	bp = bfind(name, TRUE);
151 	if (bclear(bp) != TRUE)
152 		return NULL;
153 
154 	addlinef(bp, "Running (%s).", command);
155 	addline(bp, "");
156 
157 	if ((pipe = popen(command, "r")) == NULL) {
158 		ewprintf("Problem opening pipe");
159 		return NULL;
160 	}
161 	/*
162 	 * We know that our commands are nice and the last line will end with
163 	 * a \n, so we don't need to try to deal with the last line problem
164 	 * in fgetln.
165 	 */
166 	while ((buf = fgetln(pipe, &len)) != NULL) {
167 		buf[len - 1] = '\0';
168 		addline(bp, buf);
169 	}
170 	ret = pclose(pipe);
171 	addline(bp, "");
172 	addlinef(bp, "Command (%s) completed %s.", command,
173 		ret == 0 ? "successfully" : "with errors");
174 	bp->b_dotp = lforw(bp->b_linep);	/* go to first line */
175 	bp->b_modes[0] = name_mode("fundamental");
176 	bp->b_modes[1] = name_mode("compile");
177 	bp->b_nmodes = 1;
178 
179 	compile_buffer = bp;
180 
181 	return bp;
182 }
183 
184 static int
185 compile_goto_error(int f, int n)
186 {
187 	BUFFER *bp;
188 	MGWIN *wp;
189 	char *fname, *line, *lp, *ln, *lp1;
190 	int lineno, len;
191 	char *adjf;
192 
193 	compile_win = curwp;
194 	compile_buffer = curbp;
195 
196 retry:
197 	len = llength(curwp->w_dotp);
198 
199 	if ((line = malloc(len + 1)) == NULL)
200 		return FALSE;
201 
202 	memcpy(line, curwp->w_dotp->l_text, len);
203 	line[len] = '\0';
204 
205 	lp = line;
206 	if ((fname = strsep(&lp, ":")) == NULL)
207 		goto fail;
208 	if ((ln = strsep(&lp, ":")) == NULL)
209 		goto fail;
210 	lineno = strtol(ln, &lp1, 10);
211 	if (lp != lp1 + 1)
212 		goto fail;
213 	free(line);
214 
215 	adjf = adjustname(fname);
216 	if ((bp = findbuffer(adjf)) == NULL)
217 		return FALSE;
218 	if ((wp = popbuf(bp)) == NULL)
219 		return FALSE;
220 	curbp = bp;
221 	curwp = wp;
222 	if (bp->b_fname[0] == 0)
223 		readin(adjf);
224 	gotoline(FFARG, lineno);
225 	return TRUE;
226 fail:
227  	free(line);
228 	if (curwp->w_dotp != lback(curbp->b_linep)) {
229 		curwp->w_dotp = lforw(curwp->w_dotp);
230 		curwp->w_flag |= WFMOVE;
231 		goto retry;
232 	}
233 	ewprintf("No more hits");
234  	return FALSE;
235 }
236 
237 static int
238 next_error(int f, int n)
239 {
240 	if (compile_win == NULL || compile_buffer == NULL) {
241 		ewprintf("No compilation active");
242 		return FALSE;
243 	}
244 	curwp = compile_win;
245 	curbp = compile_buffer;
246 	if (curwp->w_dotp == lback(curbp->b_linep)) {
247 		ewprintf("No more hits");
248 		return FALSE;
249 	}
250 	curwp->w_dotp = lforw(curwp->w_dotp);
251 	curwp->w_flag |= WFMOVE;
252 
253 	return compile_goto_error(f, n);
254 }
255