Annotation of src/usr.bin/mg/grep.c, Revision 1.41
1.41 ! guenther 1: /* $OpenBSD: grep.c,v 1.40 2014/03/20 07:47:29 lum Exp $ */
1.35 kjell 2:
3: /* This file is in the public domain */
1.1 art 4:
5: #include "def.h"
6: #include "kbd.h"
7: #include "funmap.h"
8:
1.18 kjell 9: #include <sys/types.h>
1.11 vincent 10: #include <ctype.h>
1.18 kjell 11: #include <libgen.h>
12: #include <time.h>
1.11 vincent 13:
1.34 kjell 14: int globalwd = FALSE;
1.13 db 15: static int compile_goto_error(int, int);
1.17 kjell 16: int next_error(int, int);
1.13 db 17: static int grep(int, int);
18: static int gid(int, int);
1.28 kjell 19: static struct buffer *compile_mode(const char *, const char *);
1.1 art 20: void grep_init(void);
21:
1.8 vincent 22: static char compile_last_command[NFILEN] = "make ";
23:
1.1 art 24: /*
25: * Hints for next-error
26: *
27: * XXX - need some kind of callback to find out when those get killed.
28: */
1.24 deraadt 29: struct mgwin *compile_win;
30: struct buffer *compile_buffer;
1.1 art 31:
32: static PF compile_pf[] = {
1.13 db 33: compile_goto_error
1.1 art 34: };
35:
36: static struct KEYMAPE (1 + IMAPEXT) compilemap = {
37: 1,
38: 1 + IMAPEXT,
39: rescan,
40: {
1.13 db 41: { CCHR('M'), CCHR('M'), compile_pf, NULL }
1.1 art 42: }
43: };
44:
45: void
46: grep_init(void)
47: {
48: funmap_add(compile_goto_error, "compile-goto-error");
49: funmap_add(next_error, "next-error");
50: funmap_add(grep, "grep");
51: funmap_add(compile, "compile");
52: funmap_add(gid, "gid");
53: maps_add((KEYMAP *)&compilemap, "compile");
54: }
55:
1.20 kjell 56: /* ARGSUSED */
1.1 art 57: static int
58: grep(int f, int n)
59: {
1.25 kjell 60: char cprompt[NFILEN], *bufp;
1.24 deraadt 61: struct buffer *bp;
62: struct mgwin *wp;
1.1 art 63:
1.25 kjell 64: (void)strlcpy(cprompt, "grep -n ", sizeof(cprompt));
65: if ((bufp = eread("Run grep: ", cprompt, NFILEN,
1.16 kjell 66: EFDEF | EFNEW | EFCR)) == NULL)
1.13 db 67: return (ABORT);
1.16 kjell 68: else if (bufp[0] == '\0')
69: return (FALSE);
1.29 kjell 70: if (strlcat(cprompt, " /dev/null", sizeof(cprompt)) >= sizeof(cprompt))
71: return (FALSE);
1.1 art 72:
1.29 kjell 73: if ((bp = compile_mode("*grep*", cprompt)) == NULL)
1.25 kjell 74: return (FALSE);
1.38 kjell 75: if ((wp = popbuf(bp, WNONE)) == NULL)
1.25 kjell 76: return (FALSE);
77: curbp = bp;
78: compile_win = curwp = wp;
79: return (TRUE);
80: }
81:
82: /* ARGSUSED */
1.36 kjell 83: int
1.1 art 84: compile(int f, int n)
85: {
1.25 kjell 86: char cprompt[NFILEN], *bufp;
1.24 deraadt 87: struct buffer *bp;
88: struct mgwin *wp;
1.1 art 89:
1.25 kjell 90: (void)strlcpy(cprompt, compile_last_command, sizeof(cprompt));
91: if ((bufp = eread("Compile command: ", cprompt, NFILEN,
1.16 kjell 92: EFDEF | EFNEW | EFCR)) == NULL)
1.14 jason 93: return (ABORT);
1.16 kjell 94: else if (bufp[0] == '\0')
95: return (FALSE);
1.14 jason 96: if (savebuffers(f, n) == ABORT)
1.13 db 97: return (ABORT);
98: (void)strlcpy(compile_last_command, bufp, sizeof(compile_last_command));
1.1 art 99:
1.29 kjell 100: if ((bp = compile_mode("*compile*", cprompt)) == NULL)
1.13 db 101: return (FALSE);
1.38 kjell 102: if ((wp = popbuf(bp, WNONE)) == NULL)
1.13 db 103: return (FALSE);
1.1 art 104: curbp = bp;
105: compile_win = curwp = wp;
1.27 kjell 106: gotoline(FFARG, 0);
1.13 db 107: return (TRUE);
1.1 art 108: }
109:
110: /* id-utils foo. */
1.20 kjell 111: /* ARGSUSED */
1.1 art 112: static int
113: gid(int f, int n)
114: {
1.29 kjell 115: char command[NFILEN];
1.41 ! guenther 116: char cprompt[NFILEN], *bufp;
! 117: int c;
1.24 deraadt 118: struct buffer *bp;
119: struct mgwin *wp;
1.29 kjell 120: int i, j, len;
1.1 art 121:
1.11 vincent 122: /* catch ([^\s(){}]+)[\s(){}]* */
123:
124: i = curwp->w_doto;
1.15 cloder 125: /* Skip backwards over delimiters we are currently on */
126: while (i > 0) {
127: c = lgetc(curwp->w_dotp, i);
128: if (isalnum(c) || c == '_')
129: break;
130:
1.11 vincent 131: i--;
1.15 cloder 132: }
133:
1.11 vincent 134: /* Skip the symbol itself */
135: for (; i > 0; i--) {
136: c = lgetc(curwp->w_dotp, i - 1);
1.15 cloder 137: if (!isalnum(c) && c != '_')
1.11 vincent 138: break;
139: }
1.25 kjell 140: /* Fill the symbol in cprompt[] */
141: for (j = 0; j < sizeof(cprompt) - 1 && i < llength(curwp->w_dotp);
1.11 vincent 142: j++, i++) {
143: c = lgetc(curwp->w_dotp, i);
1.15 cloder 144: if (!isalnum(c) && c != '_')
1.11 vincent 145: break;
1.25 kjell 146: cprompt[j] = c;
1.11 vincent 147: }
1.25 kjell 148: cprompt[j] = '\0';
1.11 vincent 149:
1.25 kjell 150: if ((bufp = eread("Run gid (with args): ", cprompt, NFILEN,
1.16 kjell 151: (j ? EFDEF : 0) | EFNEW | EFCR)) == NULL)
1.13 db 152: return (ABORT);
1.16 kjell 153: else if (bufp[0] == '\0')
154: return (FALSE);
1.29 kjell 155: len = snprintf(command, sizeof(command), "gid %s", cprompt);
156: if (len < 0 || len >= sizeof(command))
157: return (FALSE);
1.1 art 158:
1.28 kjell 159: if ((bp = compile_mode("*gid*", command)) == NULL)
1.13 db 160: return (FALSE);
1.38 kjell 161: if ((wp = popbuf(bp, WNONE)) == NULL)
1.13 db 162: return (FALSE);
1.1 art 163: curbp = bp;
164: compile_win = curwp = wp;
1.13 db 165: return (TRUE);
1.1 art 166: }
167:
1.24 deraadt 168: struct buffer *
1.28 kjell 169: compile_mode(const char *name, const char *command)
1.1 art 170: {
1.24 deraadt 171: struct buffer *bp;
1.26 kjell 172: FILE *fpipe;
1.13 db 173: char *buf;
174: size_t len;
1.29 kjell 175: int ret, n;
176: char cwd[NFILEN], qcmd[NFILEN];
1.18 kjell 177: char timestr[NTIME];
178: time_t t;
1.1 art 179:
1.29 kjell 180: n = snprintf(qcmd, sizeof(qcmd), "%s 2>&1", command);
181: if (n < 0 || n >= sizeof(qcmd))
182: return (NULL);
183:
1.1 art 184: bp = bfind(name, TRUE);
185: if (bclear(bp) != TRUE)
1.13 db 186: return (NULL);
1.1 art 187:
1.28 kjell 188: if (getbufcwd(bp->b_cwd, sizeof(bp->b_cwd)) != TRUE)
189: return (NULL);
190: addlinef(bp, "cd %s", bp->b_cwd);
1.29 kjell 191: addline(bp, qcmd);
1.1 art 192: addline(bp, "");
193:
1.23 deraadt 194: if (getcwd(cwd, sizeof(cwd)) == NULL)
1.18 kjell 195: panic("Can't get current directory!");
1.28 kjell 196: if (chdir(bp->b_cwd) == -1) {
1.40 lum 197: dobeep();
1.28 kjell 198: ewprintf("Can't change dir to %s", bp->b_cwd);
1.18 kjell 199: return (NULL);
1.19 deraadt 200: }
1.29 kjell 201: if ((fpipe = popen(qcmd, "r")) == NULL) {
1.40 lum 202: dobeep();
1.1 art 203: ewprintf("Problem opening pipe");
1.13 db 204: return (NULL);
1.1 art 205: }
206: /*
207: * We know that our commands are nice and the last line will end with
208: * a \n, so we don't need to try to deal with the last line problem
209: * in fgetln.
210: */
1.26 kjell 211: while ((buf = fgetln(fpipe, &len)) != NULL) {
1.1 art 212: buf[len - 1] = '\0';
213: addline(bp, buf);
214: }
1.26 kjell 215: ret = pclose(fpipe);
1.18 kjell 216: t = time(NULL);
217: strftime(timestr, sizeof(timestr), "%a %b %e %T %Y", localtime(&t));
1.1 art 218: addline(bp, "");
1.18 kjell 219: if (ret != 0)
220: addlinef(bp, "Command exited abnormally with code %d"
221: " at %s", ret, timestr);
222: else
223: addlinef(bp, "Command finished at %s", timestr);
224:
1.32 kjell 225: bp->b_dotp = bfirstlp(bp);
1.1 art 226: bp->b_modes[0] = name_mode("fundamental");
227: bp->b_modes[1] = name_mode("compile");
228: bp->b_nmodes = 1;
229:
230: compile_buffer = bp;
231:
1.18 kjell 232: if (chdir(cwd) == -1) {
1.40 lum 233: dobeep();
1.18 kjell 234: ewprintf("Can't change dir back to %s", cwd);
235: return (NULL);
1.19 deraadt 236: }
1.13 db 237: return (bp);
1.1 art 238: }
239:
1.20 kjell 240: /* ARGSUSED */
1.1 art 241: static int
242: compile_goto_error(int f, int n)
243: {
1.24 deraadt 244: struct buffer *bp;
245: struct mgwin *wp;
1.21 kjell 246: char *fname, *line, *lp, *ln;
1.29 kjell 247: int lineno;
1.28 kjell 248: char *adjf, path[NFILEN];
1.21 kjell 249: const char *errstr;
1.24 deraadt 250: struct line *last;
1.1 art 251:
252: compile_win = curwp;
253: compile_buffer = curbp;
1.32 kjell 254: last = blastlp(compile_buffer);
1.22 deraadt 255:
1.21 kjell 256: retry:
257: /* last line is compilation result */
258: if (curwp->w_dotp == last)
259: return (FALSE);
1.33 deraadt 260:
1.29 kjell 261: if ((line = linetostr(curwp->w_dotp)) == NULL)
1.13 db 262: return (FALSE);
1.1 art 263: lp = line;
1.21 kjell 264: if ((fname = strsep(&lp, ":")) == NULL || *fname == '\0')
1.1 art 265: goto fail;
1.21 kjell 266: if ((ln = strsep(&lp, ":")) == NULL || *ln == '\0')
1.1 art 267: goto fail;
1.24 deraadt 268: lineno = (int)strtonum(ln, INT_MIN, INT_MAX, &errstr);
1.21 kjell 269: if (errstr)
1.1 art 270: goto fail;
1.33 deraadt 271:
1.28 kjell 272: if (fname && fname[0] != '/') {
1.34 kjell 273: if (getbufcwd(path, sizeof(path)) == FALSE)
274: goto fail;
1.28 kjell 275: if (strlcat(path, fname, sizeof(path)) >= sizeof(path))
276: goto fail;
277: adjf = path;
278: } else {
1.30 jason 279: adjf = adjustname(fname, TRUE);
1.28 kjell 280: }
1.1 art 281: free(line);
282:
1.7 vincent 283: if (adjf == NULL)
284: return (FALSE);
1.10 vincent 285:
1.1 art 286: if ((bp = findbuffer(adjf)) == NULL)
1.13 db 287: return (FALSE);
1.38 kjell 288: if ((wp = popbuf(bp, WNONE)) == NULL)
1.13 db 289: return (FALSE);
1.1 art 290: curbp = bp;
291: curwp = wp;
1.27 kjell 292: if (bp->b_fname[0] == '\0')
1.1 art 293: readin(adjf);
294: gotoline(FFARG, lineno);
1.13 db 295: return (TRUE);
1.1 art 296: fail:
1.3 deraadt 297: free(line);
1.32 kjell 298: if (curwp->w_dotp != blastlp(curbp)) {
1.1 art 299: curwp->w_dotp = lforw(curwp->w_dotp);
1.37 kjell 300: curwp->w_rflag |= WFMOVE;
1.1 art 301: goto retry;
302: }
1.40 lum 303: dobeep();
1.1 art 304: ewprintf("No more hits");
1.13 db 305: return (FALSE);
1.1 art 306: }
307:
1.20 kjell 308: /* ARGSUSED */
1.17 kjell 309: int
1.1 art 310: next_error(int f, int n)
311: {
312: if (compile_win == NULL || compile_buffer == NULL) {
1.40 lum 313: dobeep();
1.1 art 314: ewprintf("No compilation active");
1.13 db 315: return (FALSE);
1.1 art 316: }
317: curwp = compile_win;
318: curbp = compile_buffer;
1.32 kjell 319: if (curwp->w_dotp == blastlp(curbp)) {
1.40 lum 320: dobeep();
1.1 art 321: ewprintf("No more hits");
1.13 db 322: return (FALSE);
1.1 art 323: }
324: curwp->w_dotp = lforw(curwp->w_dotp);
1.37 kjell 325: curwp->w_rflag |= WFMOVE;
1.1 art 326:
1.13 db 327: return (compile_goto_error(f, n));
1.34 kjell 328: }
329:
330: /*
331: * Since we don't have variables (we probably should) these are command
332: * processors for changing the values of mode flags.
333: */
334: /* ARGSUSED */
335: int
336: globalwdtoggle(int f, int n)
337: {
338: if (f & FFARG)
339: globalwd = n > 0;
340: else
341: globalwd = !globalwd;
342:
343: sgarbf = TRUE;
344:
345: return (TRUE);
1.1 art 346: }