GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mg/grep.c Lines: 0 175 0.0 %
Date: 2017-11-07 Branches: 0 104 0.0 %

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