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