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