GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ed/io.c Lines: 0 168 0.0 %
Date: 2016-12-06 Branches: 0 292 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: io.c,v 1.19 2016/03/22 17:58:28 mmcc Exp $	*/
2
/*	$NetBSD: io.c,v 1.2 1995/03/21 09:04:43 cgd Exp $	*/
3
4
/* io.c: This file contains the i/o routines for the ed line editor */
5
/*-
6
 * Copyright (c) 1993 Andrew Moore, Talke Studio.
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
31
#include <regex.h>
32
#include <signal.h>
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
37
#include "ed.h"
38
39
static int read_stream(FILE *, int);
40
static int get_stream_line(FILE *);
41
static int write_stream(FILE *, int, int);
42
static int put_stream_line(FILE *, char *, int);
43
44
extern int scripted;
45
46
/* read_file: read a named file/pipe into the buffer; return line count */
47
int
48
read_file(char *fn, int n)
49
{
50
	FILE *fp;
51
	int size;
52
53
54
	fp = (*fn == '!') ? popen(fn + 1, "r") : fopen(strip_escapes(fn), "r");
55
	if (fp == NULL) {
56
		perror(fn);
57
		seterrmsg("cannot open input file");
58
		return ERR;
59
	} else if ((size = read_stream(fp, n)) < 0)
60
		return ERR;
61
	 else if (((*fn == '!') ?  pclose(fp) : fclose(fp)) < 0) {
62
		perror(fn);
63
		seterrmsg("cannot close input file");
64
		return ERR;
65
	}
66
	fprintf(stderr, !scripted ? "%d\n" : "", size);
67
	return current_addr - n;
68
}
69
70
71
static char *sbuf;		/* file i/o buffer */
72
static int sbufsz;		/* file i/o buffer size */
73
int newline_added;		/* if set, newline appended to input file */
74
75
/* read_stream: read a stream into the editor buffer; return status */
76
static int
77
read_stream(FILE *fp, int n)
78
{
79
	line_t *lp = get_addressed_line_node(n);
80
	undo_t *up = NULL;
81
	unsigned int size = 0;
82
	int o_newline_added = newline_added;
83
	int o_isbinary = isbinary;
84
	int appended = (n == addr_last);
85
	int len;
86
87
	isbinary = newline_added = 0;
88
	for (current_addr = n; (len = get_stream_line(fp)) > 0; size += len) {
89
		SPL1();
90
		if (put_sbuf_line(sbuf) == NULL) {
91
			SPL0();
92
			return ERR;
93
		}
94
		lp = lp->q_forw;
95
		if (up)
96
			up->t = lp;
97
		else if ((up = push_undo_stack(UADD, current_addr,
98
		    current_addr)) == NULL) {
99
			SPL0();
100
			return ERR;
101
		}
102
		SPL0();
103
	}
104
	if (len < 0)
105
		return ERR;
106
	if (appended && size && o_isbinary && o_newline_added)
107
		fputs("newline inserted\n", stderr);
108
	else if (newline_added && (!appended || (!isbinary && !o_isbinary)))
109
		fputs("newline appended\n", stderr);
110
	if (isbinary && newline_added && !appended)
111
	    	size += 1;
112
	if (!size)
113
		newline_added = 1;
114
	newline_added = appended ? newline_added : o_newline_added;
115
	isbinary = isbinary | o_isbinary;
116
	return size;
117
}
118
119
/* get_stream_line: read a line of text from a stream; return line length */
120
static int
121
get_stream_line(FILE *fp)
122
{
123
	int c;
124
	int i = 0;
125
126
	while (((c = getc(fp)) != EOF || (!feof(fp) &&
127
	    !ferror(fp))) && c != '\n') {
128
		REALLOC(sbuf, sbufsz, i + 1, ERR);
129
		if (!(sbuf[i++] = c))
130
			isbinary = 1;
131
	}
132
	REALLOC(sbuf, sbufsz, i + 2, ERR);
133
	if (c == '\n')
134
		sbuf[i++] = c;
135
	else if (ferror(fp)) {
136
		perror(NULL);
137
		seterrmsg("cannot read input file");
138
		return ERR;
139
	} else if (i) {
140
		sbuf[i++] = '\n';
141
		newline_added = 1;
142
	}
143
	sbuf[i] = '\0';
144
	return (isbinary && newline_added && i) ? --i : i;
145
}
146
147
148
/* write_file: write a range of lines to a named file/pipe; return line count */
149
int
150
write_file(char *fn, char *mode, int n, int m)
151
{
152
	FILE *fp;
153
	int size;
154
155
	fp = (*fn == '!') ? popen(fn+1, "w") : fopen(strip_escapes(fn), mode);
156
	if (fp == NULL) {
157
		perror(fn);
158
		seterrmsg("cannot open output file");
159
		return ERR;
160
	} else if ((size = write_stream(fp, n, m)) < 0)
161
		return ERR;
162
	 else if (((*fn == '!') ?  pclose(fp) : fclose(fp)) < 0) {
163
		perror(fn);
164
		seterrmsg("cannot close output file");
165
		return ERR;
166
	}
167
	fprintf(stderr, !scripted ? "%d\n" : "", size);
168
	return n ? m - n + 1 : 0;
169
}
170
171
172
/* write_stream: write a range of lines to a stream; return status */
173
static int
174
write_stream(FILE *fp, int n, int m)
175
{
176
	line_t *lp = get_addressed_line_node(n);
177
	unsigned int size = 0;
178
	char *s;
179
	int len;
180
181
	for (; n && n <= m; n++, lp = lp->q_forw) {
182
		if ((s = get_sbuf_line(lp)) == NULL)
183
			return ERR;
184
		len = lp->len;
185
		if (n != addr_last || !isbinary || !newline_added)
186
			s[len++] = '\n';
187
		if (put_stream_line(fp, s, len) < 0)
188
			return ERR;
189
		size += len;
190
	}
191
	return size;
192
}
193
194
195
/* put_stream_line: write a line of text to a stream; return status */
196
static int
197
put_stream_line(FILE *fp, char *s, int len)
198
{
199
	while (len--) {
200
		if (fputc(*s, fp) < 0) {
201
			perror(NULL);
202
			seterrmsg("cannot write file");
203
			return ERR;
204
		}
205
		s++;
206
	}
207
	return 0;
208
}
209
210
/* get_extended_line: get a an extended line from stdin */
211
char *
212
get_extended_line(int *sizep, int nonl)
213
{
214
	static char *cvbuf = NULL;		/* buffer */
215
	static int cvbufsz = 0;			/* buffer size */
216
217
	int l, n;
218
	char *t = ibufp;
219
220
	while (*t++ != '\n')
221
		;
222
	if ((l = t - ibufp) < 2 || !has_trailing_escape(ibufp, ibufp + l - 1)) {
223
		*sizep = l;
224
		return ibufp;
225
	}
226
	*sizep = -1;
227
	REALLOC(cvbuf, cvbufsz, l, NULL);
228
	memcpy(cvbuf, ibufp, l);
229
	*(cvbuf + --l - 1) = '\n'; 	/* strip trailing esc */
230
	if (nonl)
231
		l--; 			/* strip newline */
232
	for (;;) {
233
		if ((n = get_tty_line()) < 0)
234
			return NULL;
235
		else if (n == 0 || ibuf[n - 1] != '\n') {
236
			seterrmsg("unexpected end-of-file");
237
			return NULL;
238
		}
239
		REALLOC(cvbuf, cvbufsz, l + n, NULL);
240
		memcpy(cvbuf + l, ibuf, n);
241
		l += n;
242
		if (n < 2 || !has_trailing_escape(cvbuf, cvbuf + l - 1))
243
			break;
244
		*(cvbuf + --l - 1) = '\n'; 	/* strip trailing esc */
245
		if (nonl) l--; 			/* strip newline */
246
	}
247
	REALLOC(cvbuf, cvbufsz, l + 1, NULL);
248
	cvbuf[l] = '\0';
249
	*sizep = l;
250
	return cvbuf;
251
}
252
253
254
/* get_tty_line: read a line of text from stdin; return line length */
255
int
256
get_tty_line(void)
257
{
258
	int oi = 0;
259
	int i = 0;
260
	int c;
261
262
	for (;;)
263
		switch (c = getchar()) {
264
		default:
265
			oi = 0;
266
			REALLOC(ibuf, ibufsz, i + 2, ERR);
267
			if (!(ibuf[i++] = c)) isbinary = 1;
268
			if (c != '\n')
269
				continue;
270
			lineno++;
271
			ibuf[i] = '\0';
272
			ibufp = ibuf;
273
			return i;
274
		case EOF:
275
			if (ferror(stdin)) {
276
				perror("stdin");
277
				seterrmsg("cannot read stdin");
278
				clearerr(stdin);
279
				ibufp = NULL;
280
				return ERR;
281
			} else {
282
				clearerr(stdin);
283
				if (i != oi) {
284
					oi = i;
285
					continue;
286
				} else if (i)
287
					ibuf[i] = '\0';
288
				ibufp = ibuf;
289
				return i;
290
			}
291
		}
292
}
293
294
295
296
#define ESCAPES "\a\b\f\n\r\t\v\\"
297
#define ESCCHARS "abfnrtv\\"
298
299
extern int rows;
300
extern int cols;
301
302
/* put_tty_line: print text to stdout */
303
int
304
put_tty_line(char *s, int l, int n, int gflag)
305
{
306
	int col = 0;
307
#ifndef BACKWARDS
308
	int lc = 0;
309
#endif
310
	char *cp;
311
312
	if (gflag & GNP) {
313
		printf("%d\t", n);
314
		col = 8;
315
	}
316
	for (; l--; s++) {
317
		if ((gflag & GLS) && ++col > cols) {
318
			fputs("\\\n", stdout);
319
			col = 1;
320
#ifndef BACKWARDS
321
			if (!scripted && !isglobal && ++lc > rows) {
322
				lc = 0;
323
				fputs("Press <RETURN> to continue... ", stdout);
324
				fflush(stdout);
325
				if (get_tty_line() < 0)
326
					return ERR;
327
			}
328
#endif
329
		}
330
		if (gflag & GLS) {
331
			if (31 < *s && *s < 127 && *s != '\\')
332
				putchar(*s);
333
			else {
334
				putchar('\\');
335
				col++;
336
				if (*s && (cp = strchr(ESCAPES, *s)) != NULL)
337
					putchar(ESCCHARS[cp - ESCAPES]);
338
				else {
339
					putchar((((unsigned char) *s & 0300) >> 6) + '0');
340
					putchar((((unsigned char) *s & 070) >> 3) + '0');
341
					putchar(((unsigned char) *s & 07) + '0');
342
					col += 2;
343
				}
344
			}
345
346
		} else
347
			putchar(*s);
348
	}
349
#ifndef BACKWARDS
350
	if (gflag & GLS)
351
		putchar('$');
352
#endif
353
	putchar('\n');
354
	return 0;
355
}