GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/vi/build/../ex/ex_args.c Lines: 0 126 0.0 %
Date: 2017-11-07 Branches: 0 96 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ex_args.c,v 1.12 2016/01/06 22:28:52 millert Exp $	*/
2
3
/*-
4
 * Copyright (c) 1991, 1993, 1994
5
 *	The Regents of the University of California.  All rights reserved.
6
 * Copyright (c) 1991, 1993, 1994, 1995, 1996
7
 *	Keith Bostic.  All rights reserved.
8
 *
9
 * See the LICENSE file for redistribution information.
10
 */
11
12
#include "config.h"
13
14
#include <sys/types.h>
15
#include <sys/queue.h>
16
#include <sys/time.h>
17
18
#include <bitstring.h>
19
#include <errno.h>
20
#include <limits.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include "../common/common.h"
26
#include "../vi/vi.h"
27
28
static int ex_N_next(SCR *, EXCMD *);
29
30
/*
31
 * ex_next -- :next [+cmd] [files]
32
 *	Edit the next file, optionally setting the list of files.
33
 *
34
 * !!!
35
 * The :next command behaved differently from the :rewind command in
36
 * historic vi.  See nvi/docs/autowrite for details, but the basic
37
 * idea was that it ignored the force flag if the autowrite flag was
38
 * set.  This implementation handles them all identically.
39
 *
40
 * PUBLIC: int ex_next(SCR *, EXCMD *);
41
 */
42
int
43
ex_next(SCR *sp, EXCMD *cmdp)
44
{
45
	ARGS **argv;
46
	FREF *frp;
47
	int noargs;
48
	char **ap;
49
50
	/* Check for file to move to. */
51
	if (cmdp->argc == 0 && (sp->cargv == NULL || sp->cargv[1] == NULL)) {
52
		msgq(sp, M_ERR, "No more files to edit");
53
		return (1);
54
	}
55
56
	if (F_ISSET(cmdp, E_NEWSCREEN)) {
57
		/* By default, edit the next file in the old argument list. */
58
		if (cmdp->argc == 0) {
59
			if (argv_exp0(sp,
60
			    cmdp, sp->cargv[1], strlen(sp->cargv[1])))
61
				return (1);
62
			return (ex_edit(sp, cmdp));
63
		}
64
		return (ex_N_next(sp, cmdp));
65
	}
66
67
	/* Check modification. */
68
	if (file_m1(sp,
69
	    FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
70
		return (1);
71
72
	/* Any arguments are a replacement file list. */
73
	if (cmdp->argc) {
74
		/* Free the current list. */
75
		if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
76
			for (ap = sp->argv; *ap != NULL; ++ap)
77
				free(*ap);
78
			free(sp->argv);
79
		}
80
		F_CLR(sp, SC_ARGNOFREE | SC_ARGRECOVER);
81
		sp->cargv = NULL;
82
83
		/* Create a new list. */
84
		CALLOC_RET(sp,
85
		    sp->argv, cmdp->argc + 1, sizeof(char *));
86
		for (ap = sp->argv,
87
		    argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv)
88
			if ((*ap =
89
			    v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL)
90
				return (1);
91
		*ap = NULL;
92
93
		/* Switch to the first file. */
94
		sp->cargv = sp->argv;
95
		if ((frp = file_add(sp, *sp->cargv)) == NULL)
96
			return (1);
97
		noargs = 0;
98
99
		/* Display a file count with the welcome message. */
100
		F_SET(sp, SC_STATUS_CNT);
101
	} else {
102
		if ((frp = file_add(sp, sp->cargv[1])) == NULL)
103
			return (1);
104
		if (F_ISSET(sp, SC_ARGRECOVER))
105
			F_SET(frp, FR_RECOVER);
106
		noargs = 1;
107
	}
108
109
	if (file_init(sp, frp, NULL, FS_SETALT |
110
	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
111
		return (1);
112
	if (noargs)
113
		++sp->cargv;
114
115
	F_SET(sp, SC_FSWITCH);
116
	return (0);
117
}
118
119
/*
120
 * ex_N_next --
121
 *	New screen version of ex_next.
122
 */
123
static int
124
ex_N_next(SCR *sp, EXCMD *cmdp)
125
{
126
	SCR *new;
127
	FREF *frp;
128
129
	/* Get a new screen. */
130
	if (screen_init(sp->gp, sp, &new))
131
		return (1);
132
	if (vs_split(sp, new, 0)) {
133
		(void)screen_end(new);
134
		return (1);
135
	}
136
137
	/* Get a backing file. */
138
	if ((frp = file_add(new, cmdp->argv[0]->bp)) == NULL ||
139
	    file_init(new, frp, NULL,
140
	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
141
		(void)vs_discard(new, NULL);
142
		(void)screen_end(new);
143
		return (1);
144
	}
145
146
	/* The arguments are a replacement file list. */
147
	new->cargv = new->argv = ex_buildargv(sp, cmdp, NULL);
148
149
	/* Display a file count with the welcome message. */
150
	F_SET(new, SC_STATUS_CNT);
151
152
	/* Set up the switch. */
153
	sp->nextdisp = new;
154
	F_SET(sp, SC_SSWITCH);
155
156
	return (0);
157
}
158
159
/*
160
 * ex_prev -- :prev
161
 *	Edit the previous file.
162
 *
163
 * PUBLIC: int ex_prev(SCR *, EXCMD *);
164
 */
165
int
166
ex_prev(SCR *sp, EXCMD *cmdp)
167
{
168
	FREF *frp;
169
170
	if (sp->cargv == sp->argv) {
171
		msgq(sp, M_ERR, "No previous files to edit");
172
		return (1);
173
	}
174
175
	if (F_ISSET(cmdp, E_NEWSCREEN)) {
176
		if (argv_exp0(sp, cmdp, sp->cargv[-1], strlen(sp->cargv[-1])))
177
			return (1);
178
		return (ex_edit(sp, cmdp));
179
	}
180
181
	if (file_m1(sp,
182
	    FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
183
		return (1);
184
185
	if ((frp = file_add(sp, sp->cargv[-1])) == NULL)
186
		return (1);
187
188
	if (file_init(sp, frp, NULL, FS_SETALT |
189
	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
190
		return (1);
191
	--sp->cargv;
192
193
	F_SET(sp, SC_FSWITCH);
194
	return (0);
195
}
196
197
/*
198
 * ex_rew -- :rew
199
 *	Re-edit the list of files.
200
 *
201
 * !!!
202
 * Historic practice was that all files would start editing at the beginning
203
 * of the file.  We don't get this right because we may have multiple screens
204
 * and we can't clear the FR_CURSORSET bit for a single screen.  I don't see
205
 * anyone noticing, but if they do, we'll have to put information into the SCR
206
 * structure so we can keep track of it.
207
 *
208
 * PUBLIC: int ex_rew(SCR *, EXCMD *);
209
 */
210
int
211
ex_rew(SCR *sp, EXCMD *cmdp)
212
{
213
	FREF *frp;
214
215
	/*
216
	 * !!!
217
	 * Historic practice -- you can rewind to the current file.
218
	 */
219
	if (sp->argv == NULL) {
220
		msgq(sp, M_ERR, "No previous files to rewind");
221
		return (1);
222
	}
223
224
	if (file_m1(sp,
225
	    FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
226
		return (1);
227
228
	/* Switch to the first one. */
229
	sp->cargv = sp->argv;
230
	if ((frp = file_add(sp, *sp->cargv)) == NULL)
231
		return (1);
232
	if (file_init(sp, frp, NULL, FS_SETALT |
233
	    (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
234
		return (1);
235
236
	/* Switch and display a file count with the welcome message. */
237
	F_SET(sp, SC_FSWITCH | SC_STATUS_CNT);
238
239
	return (0);
240
}
241
242
/*
243
 * ex_args -- :args
244
 *	Display the list of files.
245
 *
246
 * PUBLIC: int ex_args(SCR *, EXCMD *);
247
 */
248
int
249
ex_args(SCR *sp, EXCMD *cmdp)
250
{
251
	int cnt, col, len, sep;
252
	char **ap;
253
254
	if (sp->argv == NULL) {
255
		(void)msgq(sp, M_ERR, "No file list to display");
256
		return (0);
257
	}
258
259
	col = len = sep = 0;
260
	for (cnt = 1, ap = sp->argv; *ap != NULL; ++ap) {
261
		col += len = strlen(*ap) + sep + (ap == sp->cargv ? 2 : 0);
262
		if (col >= sp->cols - 1) {
263
			col = len;
264
			sep = 0;
265
			(void)ex_puts(sp, "\n");
266
		} else if (cnt != 1) {
267
			sep = 1;
268
			(void)ex_puts(sp, " ");
269
		}
270
		++cnt;
271
272
		(void)ex_printf(sp, "%s%s%s", ap == sp->cargv ? "[" : "",
273
		    *ap, ap == sp->cargv ? "]" : "");
274
		if (INTERRUPTED(sp))
275
			break;
276
	}
277
	(void)ex_puts(sp, "\n");
278
	return (0);
279
}
280
281
/*
282
 * ex_buildargv --
283
 *	Build a new file argument list.
284
 *
285
 * PUBLIC: char **ex_buildargv(SCR *, EXCMD *, char *);
286
 */
287
char **
288
ex_buildargv(SCR *sp, EXCMD *cmdp, char *name)
289
{
290
	ARGS **argv;
291
	int argc;
292
	char **ap, **s_argv;
293
294
	argc = cmdp == NULL ? 1 : cmdp->argc;
295
	CALLOC(sp, s_argv, argc + 1, sizeof(char *));
296
	if ((ap = s_argv) == NULL)
297
		return (NULL);
298
299
	if (cmdp == NULL) {
300
		if ((*ap = v_strdup(sp, name, strlen(name))) == NULL) {
301
			free(s_argv);
302
			return (NULL);
303
		}
304
		++ap;
305
	} else
306
		for (argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv)
307
			if ((*ap =
308
			    v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL) {
309
				while (--ap >= s_argv)
310
					free(*ap);
311
				free(s_argv);
312
				return (NULL);
313
			}
314
	*ap = NULL;
315
	return (s_argv);
316
}