Annotation of src/usr.bin/mg/grep.c, Revision 1.12
1.12 ! vincent 1: /* $OpenBSD: grep.c,v 1.11 2004/06/12 15:04:41 vincent Exp $ */
1.1 art 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:
1.11 vincent 30: #include <ctype.h>
31:
1.9 vincent 32: static int compile_goto_error(int, int);
33: static int next_error(int, int);
1.1 art 34: static int grep(int, int);
35: static int compile(int, int);
36: static int gid(int, int);
1.9 vincent 37: static BUFFER *compile_mode(char *, char *);
1.1 art 38:
39:
40: void grep_init(void);
41:
1.8 vincent 42: static char compile_last_command[NFILEN] = "make ";
43:
1.1 art 44: /*
45: * Hints for next-error
46: *
47: * XXX - need some kind of callback to find out when those get killed.
48: */
49: MGWIN *compile_win;
50: BUFFER *compile_buffer;
51:
52: static PF compile_pf[] = {
53: compile_goto_error,
54: };
55:
56: static struct KEYMAPE (1 + IMAPEXT) compilemap = {
57: 1,
58: 1 + IMAPEXT,
59: rescan,
60: {
61: { CCHR('M'), CCHR('M'), compile_pf, NULL },
62: }
63: };
64:
65: void
66: grep_init(void)
67: {
68: funmap_add(compile_goto_error, "compile-goto-error");
69: funmap_add(next_error, "next-error");
70: funmap_add(grep, "grep");
71: funmap_add(compile, "compile");
72: funmap_add(gid, "gid");
73: maps_add((KEYMAP *)&compilemap, "compile");
74: }
75:
76: static int
77: grep(int f, int n)
78: {
79: char command[NFILEN + 20];
1.12 ! vincent 80: char prompt[NFILEN], *bufp;
1.1 art 81: BUFFER *bp;
82: MGWIN *wp;
83:
1.6 vincent 84: (void)strlcpy(prompt, "grep -n ", sizeof prompt);
1.12 ! vincent 85: if ((bufp = eread("Run grep: ", prompt, NFILEN, EFDEF|EFNEW|EFCR))
! 86: == NULL)
1.1 art 87: return ABORT;
88:
1.12 ! vincent 89: (void)snprintf(command, sizeof command, "%s /dev/null", bufp);
1.1 art 90:
91: if ((bp = compile_mode("*grep*", command)) == NULL)
92: return FALSE;
93: if ((wp = popbuf(bp)) == NULL)
94: return FALSE;
95: curbp = bp;
96: compile_win = curwp = wp;
97: return TRUE;
98: }
99:
100: static int
101: compile(int f, int n)
102: {
103: char command[NFILEN + 20];
1.12 ! vincent 104: char prompt[NFILEN], *bufp;
1.1 art 105: BUFFER *bp;
106: MGWIN *wp;
107:
1.8 vincent 108: (void)strlcpy(prompt, compile_last_command, sizeof prompt);
1.12 ! vincent 109: if ((bufp = eread("Compile command: ", prompt, NFILEN, EFDEF|EFNEW|EFCR)) == NULL)
1.1 art 110: return ABORT;
1.12 ! vincent 111: (void)strlcpy(compile_last_command, bufp, sizeof compile_last_command);
1.1 art 112:
1.12 ! vincent 113: (void)snprintf(command, sizeof command, "%s 2>&1", bufp);
1.1 art 114:
115: if ((bp = compile_mode("*compile*", command)) == NULL)
116: return FALSE;
117: if ((wp = popbuf(bp)) == NULL)
118: return FALSE;
119: curbp = bp;
120: compile_win = curwp = wp;
121: return TRUE;
122: }
123:
124: /* id-utils foo. */
125: static int
126: gid(int f, int n)
127: {
128: char command[NFILEN + 20];
1.12 ! vincent 129: char prompt[NFILEN], c, *bufp;
1.1 art 130: BUFFER *bp;
131: MGWIN *wp;
1.11 vincent 132: int i, j;
1.1 art 133:
1.11 vincent 134: /* catch ([^\s(){}]+)[\s(){}]* */
135:
136: i = curwp->w_doto;
137: /* Skip delimiters we are currently on */
138: while (i > 0 && ((c = lgetc(curwp->w_dotp, i)) == '(' || c == ')' ||
139: c == '{' || c == '}' || isspace(c)))
140: i--;
141: /* Skip the symbol itself */
142: for (; i > 0; i--) {
143: c = lgetc(curwp->w_dotp, i - 1);
144: if (isspace(c) || c == '(' || c == ')' ||
145: c == '{' || c == '}')
146: break;
147: }
148: /* Fill the symbol in prompt[] */
149: for (j = 0; j < sizeof(prompt) - 1 && i < llength(curwp->w_dotp);
150: j++, i++) {
151: c = lgetc(curwp->w_dotp, i);
152: if (isspace(c) || c == '(' || c == ')' ||
153: c == '{' || c == '}')
154: break;
155: prompt[j] = c;
156: }
157: prompt[j] = '\0';
158:
1.12 ! vincent 159: if ((bufp = eread("Run gid (with args): ", prompt, NFILEN,
! 160: (j ? EFDEF : 0)|EFNEW|EFCR)) == NULL)
1.1 art 161: return ABORT;
1.6 vincent 162: (void)snprintf(command, sizeof command, "gid %s", prompt);
1.1 art 163:
164: if ((bp = compile_mode("*gid*", command)) == NULL)
165: return FALSE;
166: if ((wp = popbuf(bp)) == NULL)
167: return FALSE;
168: curbp = bp;
169: compile_win = curwp = wp;
170: return TRUE;
171: }
172:
173: BUFFER *
174: compile_mode(char *name, char *command)
175: {
176: BUFFER *bp;
177: FILE *pipe;
178: char *buf;
179: size_t len;
180: int ret;
181:
182: bp = bfind(name, TRUE);
183: if (bclear(bp) != TRUE)
184: return NULL;
185:
1.3 deraadt 186: addlinef(bp, "Running (%s).", command);
1.1 art 187: addline(bp, "");
188:
189: if ((pipe = popen(command, "r")) == NULL) {
190: ewprintf("Problem opening pipe");
191: return NULL;
192: }
193: /*
194: * We know that our commands are nice and the last line will end with
195: * a \n, so we don't need to try to deal with the last line problem
196: * in fgetln.
197: */
198: while ((buf = fgetln(pipe, &len)) != NULL) {
199: buf[len - 1] = '\0';
200: addline(bp, buf);
201: }
202: ret = pclose(pipe);
203: addline(bp, "");
204: addlinef(bp, "Command (%s) completed %s.", command,
205: ret == 0 ? "successfully" : "with errors");
206: bp->b_dotp = lforw(bp->b_linep); /* go to first line */
207: bp->b_modes[0] = name_mode("fundamental");
208: bp->b_modes[1] = name_mode("compile");
209: bp->b_nmodes = 1;
210:
211: compile_buffer = bp;
212:
213: return bp;
214: }
215:
216: static int
217: compile_goto_error(int f, int n)
218: {
219: BUFFER *bp;
220: MGWIN *wp;
221: char *fname, *line, *lp, *ln, *lp1;
222: int lineno, len;
223: char *adjf;
224:
225: compile_win = curwp;
226: compile_buffer = curbp;
227:
228: retry:
229: len = llength(curwp->w_dotp);
230:
231: if ((line = malloc(len + 1)) == NULL)
232: return FALSE;
233:
1.6 vincent 234: (void)memcpy(line, curwp->w_dotp->l_text, len);
1.1 art 235: line[len] = '\0';
236:
237: lp = line;
238: if ((fname = strsep(&lp, ":")) == NULL)
239: goto fail;
240: if ((ln = strsep(&lp, ":")) == NULL)
241: goto fail;
242: lineno = strtol(ln, &lp1, 10);
243: if (lp != lp1 + 1)
244: goto fail;
1.10 vincent 245:
246: adjf = adjustname(fname);
1.1 art 247: free(line);
248:
1.7 vincent 249: if (adjf == NULL)
250: return (FALSE);
1.10 vincent 251:
1.1 art 252: if ((bp = findbuffer(adjf)) == NULL)
253: return FALSE;
254: if ((wp = popbuf(bp)) == NULL)
255: return FALSE;
256: curbp = bp;
257: curwp = wp;
258: if (bp->b_fname[0] == 0)
259: readin(adjf);
260: gotoline(FFARG, lineno);
261: return TRUE;
262: fail:
1.3 deraadt 263: free(line);
1.1 art 264: if (curwp->w_dotp != lback(curbp->b_linep)) {
265: curwp->w_dotp = lforw(curwp->w_dotp);
266: curwp->w_flag |= WFMOVE;
267: goto retry;
268: }
269: ewprintf("No more hits");
1.3 deraadt 270: return FALSE;
1.1 art 271: }
272:
273: static int
274: next_error(int f, int n)
275: {
276: if (compile_win == NULL || compile_buffer == NULL) {
277: ewprintf("No compilation active");
278: return FALSE;
279: }
280: curwp = compile_win;
281: curbp = compile_buffer;
282: if (curwp->w_dotp == lback(curbp->b_linep)) {
283: ewprintf("No more hits");
284: return FALSE;
285: }
286: curwp->w_dotp = lforw(curwp->w_dotp);
287: curwp->w_flag |= WFMOVE;
288:
289: return compile_goto_error(f, n);
290: }