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