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