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