PageRenderTime 28ms CodeModel.GetById 15ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/ed/buf.c

https://bitbucket.org/freebsd/freebsd-head/
C | 287 lines | 198 code | 38 blank | 51 comment | 45 complexity | 4ccdd1ddc477763911c6831d14b8c167 MD5 | raw file
  1/* buf.c: This file contains the scratch-file buffer routines for the
  2   ed line editor. */
  3/*-
  4 * Copyright (c) 1993 Andrew Moore, Talke Studio.
  5 * All rights reserved.
  6 *
  7 * Redistribution and use in source and binary forms, with or without
  8 * modification, are permitted provided that the following conditions
  9 * are met:
 10 * 1. Redistributions of source code must retain the above copyright
 11 *    notice, this list of conditions and the following disclaimer.
 12 * 2. Redistributions in binary form must reproduce the above copyright
 13 *    notice, this list of conditions and the following disclaimer in the
 14 *    documentation and/or other materials provided with the distribution.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 26 * SUCH DAMAGE.
 27 */
 28
 29#include <sys/cdefs.h>
 30__FBSDID("$FreeBSD$");
 31
 32#include <sys/file.h>
 33#include <sys/stat.h>
 34
 35#include "ed.h"
 36
 37
 38FILE *sfp;				/* scratch file pointer */
 39off_t sfseek;				/* scratch file position */
 40int seek_write;				/* seek before writing */
 41line_t buffer_head;			/* incore buffer */
 42
 43/* get_sbuf_line: get a line of text from the scratch file; return pointer
 44   to the text */
 45char *
 46get_sbuf_line(line_t *lp)
 47{
 48	static char *sfbuf = NULL;	/* buffer */
 49	static int sfbufsz = 0;		/* buffer size */
 50
 51	int len, ct;
 52
 53	if (lp == &buffer_head)
 54		return NULL;
 55	seek_write = 1;				/* force seek on write */
 56	/* out of position */
 57	if (sfseek != lp->seek) {
 58		sfseek = lp->seek;
 59		if (fseeko(sfp, sfseek, SEEK_SET) < 0) {
 60			fprintf(stderr, "%s\n", strerror(errno));
 61			errmsg = "cannot seek temp file";
 62			return NULL;
 63		}
 64	}
 65	len = lp->len;
 66	REALLOC(sfbuf, sfbufsz, len + 1, NULL);
 67	if ((ct = fread(sfbuf, sizeof(char), len, sfp)) <  0 || ct != len) {
 68		fprintf(stderr, "%s\n", strerror(errno));
 69		errmsg = "cannot read temp file";
 70		return NULL;
 71	}
 72	sfseek += len;				/* update file position */
 73	sfbuf[len] = '\0';
 74	return sfbuf;
 75}
 76
 77
 78/* put_sbuf_line: write a line of text to the scratch file and add a line node
 79   to the editor buffer;  return a pointer to the end of the text */
 80const char *
 81put_sbuf_line(const char *cs)
 82{
 83	line_t *lp;
 84	int len, ct;
 85	const char *s;
 86
 87	if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) {
 88		fprintf(stderr, "%s\n", strerror(errno));
 89		errmsg = "out of memory";
 90		return NULL;
 91	}
 92	/* assert: cs is '\n' terminated */
 93	for (s = cs; *s != '\n'; s++)
 94		;
 95	if (s - cs >= LINECHARS) {
 96		errmsg = "line too long";
 97		free(lp);
 98		return NULL;
 99	}
100	len = s - cs;
101	/* out of position */
102	if (seek_write) {
103		if (fseeko(sfp, (off_t)0, SEEK_END) < 0) {
104			fprintf(stderr, "%s\n", strerror(errno));
105			errmsg = "cannot seek temp file";
106			free(lp);
107			return NULL;
108		}
109		sfseek = ftello(sfp);
110		seek_write = 0;
111	}
112	/* assert: SPL1() */
113	if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
114		sfseek = -1;
115		fprintf(stderr, "%s\n", strerror(errno));
116		errmsg = "cannot write temp file";
117		free(lp);
118		return NULL;
119	}
120	lp->len = len;
121	lp->seek  = sfseek;
122	add_line_node(lp);
123	sfseek += len;			/* update file position */
124	return ++s;
125}
126
127
128/* add_line_node: add a line node in the editor buffer after the current line */
129void
130add_line_node(line_t *lp)
131{
132	line_t *cp;
133
134	cp = get_addressed_line_node(current_addr);				/* this get_addressed_line_node last! */
135	INSQUE(lp, cp);
136	addr_last++;
137	current_addr++;
138}
139
140
141/* get_line_node_addr: return line number of pointer */
142long
143get_line_node_addr(line_t *lp)
144{
145	line_t *cp = &buffer_head;
146	long n = 0;
147
148	while (cp != lp && (cp = cp->q_forw) != &buffer_head)
149		n++;
150	if (n && cp == &buffer_head) {
151		errmsg = "invalid address";
152		return ERR;
153	 }
154	 return n;
155}
156
157
158/* get_addressed_line_node: return pointer to a line node in the editor buffer */
159line_t *
160get_addressed_line_node(long n)
161{
162	static line_t *lp = &buffer_head;
163	static long on = 0;
164
165	SPL1();
166	if (n > on)
167		if (n <= (on + addr_last) >> 1)
168			for (; on < n; on++)
169				lp = lp->q_forw;
170		else {
171			lp = buffer_head.q_back;
172			for (on = addr_last; on > n; on--)
173				lp = lp->q_back;
174		}
175	else
176		if (n >= on >> 1)
177			for (; on > n; on--)
178				lp = lp->q_back;
179		else {
180			lp = &buffer_head;
181			for (on = 0; on < n; on++)
182				lp = lp->q_forw;
183		}
184	SPL0();
185	return lp;
186}
187
188
189extern int newline_added;
190
191char sfn[15] = "";				/* scratch file name */
192
193/* open_sbuf: open scratch file */
194int
195open_sbuf(void)
196{
197	int fd;
198	int u;
199
200	isbinary = newline_added = 0;
201	u = umask(077);
202	strcpy(sfn, "/tmp/ed.XXXXXX");
203	if ((fd = mkstemp(sfn)) == -1 ||
204	    (sfp = fdopen(fd, "w+")) == NULL) {
205		if (fd != -1)
206			close(fd);
207		perror(sfn);
208		errmsg = "cannot open temp file";
209		umask(u);
210		return ERR;
211	}
212	umask(u);
213	return 0;
214}
215
216
217/* close_sbuf: close scratch file */
218int
219close_sbuf(void)
220{
221	if (sfp) {
222		if (fclose(sfp) < 0) {
223			fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
224			errmsg = "cannot close temp file";
225			return ERR;
226		}
227		sfp = NULL;
228		unlink(sfn);
229	}
230	sfseek = seek_write = 0;
231	return 0;
232}
233
234
235/* quit: remove_lines scratch file and exit */
236void
237quit(int n)
238{
239	if (sfp) {
240		fclose(sfp);
241		unlink(sfn);
242	}
243	exit(n);
244}
245
246
247unsigned char ctab[256];		/* character translation table */
248
249/* init_buffers: open scratch buffer; initialize line queue */
250void
251init_buffers(void)
252{
253	int i = 0;
254
255	/* Read stdin one character at a time to avoid i/o contention
256	   with shell escapes invoked by nonterminal input, e.g.,
257	   ed - <<EOF
258	   !cat
259	   hello, world
260	   EOF */
261	setbuffer(stdin, stdinbuf, 1);
262
263	/* Ensure stdout is line buffered. This avoids bogus delays
264	   of output if stdout is piped through utilities to a terminal. */
265	setvbuf(stdout, NULL, _IOLBF, 0);
266	if (open_sbuf() < 0)
267		quit(2);
268	REQUE(&buffer_head, &buffer_head);
269	for (i = 0; i < 256; i++)
270		ctab[i] = i;
271}
272
273
274/* translit_text: translate characters in a string */
275char *
276translit_text(char *s, int len, int from, int to)
277{
278	static int i = 0;
279
280	unsigned char *us;
281
282	ctab[i] = i;			/* restore table to initial state */
283	ctab[i = from] = to;
284	for (us = (unsigned char *) s; len-- > 0; us++)
285		*us = ctab[*us];
286	return s;
287}