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