1 /* buf.c: This file contains the scratch-file buffer routines for the
4 * Copyright (c) 1993 Andrew Moore, Talke Studio.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
28 * @(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp
29 * $FreeBSD: src/bin/ed/buf.c,v 1.17 1999/08/27 23:14:12 peter Exp $
30 * $DragonFly: src/bin/ed/buf.c,v 1.2 2003/06/17 04:22:49 dillon Exp $
39 FILE *sfp; /* scratch file pointer */
40 off_t sfseek; /* scratch file position */
41 int seek_write; /* seek before writing */
42 line_t buffer_head; /* incore buffer */
44 /* get_sbuf_line: get a line of text from the scratch file; return pointer
50 static char *sfbuf = NULL; /* buffer */
51 static int sfbufsz = 0; /* buffer size */
55 if (lp == &buffer_head)
57 seek_write = 1; /* force seek on write */
59 if (sfseek != lp->seek) {
61 if (fseek(sfp, sfseek, SEEK_SET) < 0) {
62 fprintf(stderr, "%s\n", strerror(errno));
63 sprintf(errmsg, "cannot seek temp file");
68 REALLOC(sfbuf, sfbufsz, len + 1, NULL);
69 if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) {
70 fprintf(stderr, "%s\n", strerror(errno));
71 sprintf(errmsg, "cannot read temp file");
74 sfseek += len; /* update file position */
80 /* put_sbuf_line: write a line of text to the scratch file and add a line node
81 to the editor buffer; return a pointer to the end of the text */
90 if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) {
91 fprintf(stderr, "%s\n", strerror(errno));
92 sprintf(errmsg, "out of memory");
95 /* assert: cs is '\n' terminated */
96 for (s = cs; *s != '\n'; s++)
98 if (s - cs >= LINECHARS) {
99 sprintf(errmsg, "line too long");
103 /* out of position */
105 if (fseek(sfp, 0L, SEEK_END) < 0) {
106 fprintf(stderr, "%s\n", strerror(errno));
107 sprintf(errmsg, "cannot seek temp file");
114 if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
116 fprintf(stderr, "%s\n", strerror(errno));
117 sprintf(errmsg, "cannot write temp file");
123 sfseek += len; /* update file position */
128 /* add_line_node: add a line node in the editor buffer after the current line */
135 cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */
142 /* get_line_node_addr: return line number of pointer */
144 get_line_node_addr(lp)
147 line_t *cp = &buffer_head;
150 while (cp != lp && (cp = cp->q_forw) != &buffer_head)
152 if (n && cp == &buffer_head) {
153 sprintf(errmsg, "invalid address");
160 /* get_addressed_line_node: return pointer to a line node in the editor buffer */
162 get_addressed_line_node(n)
165 static line_t *lp = &buffer_head;
170 if (n <= (on + addr_last) >> 1)
174 lp = buffer_head.q_back;
175 for (on = addr_last; on > n; on--)
184 for (on = 0; on < n; on++)
192 extern int newline_added;
194 char sfn[15] = ""; /* scratch file name */
196 /* open_sbuf: open scratch file */
203 isbinary = newline_added = 0;
205 strcpy(sfn, "/tmp/ed.XXXXXX");
206 if ((fd = mkstemp(sfn)) == -1 ||
207 (sfp = fdopen(fd, "w+")) == NULL) {
211 strcpy(errmsg, "cannot open temp file");
220 /* close_sbuf: close scratch file */
225 if (fclose(sfp) < 0) {
226 fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
227 sprintf(errmsg, "cannot close temp file");
233 sfseek = seek_write = 0;
238 /* quit: remove_lines scratch file and exit */
251 unsigned char ctab[256]; /* character translation table */
253 /* init_buffers: open scratch buffer; initialize line queue */
259 /* Read stdin one character at a time to avoid i/o contention
260 with shell escapes invoked by nonterminal input, e.g.,
265 setbuffer(stdin, stdinbuf, 1);
267 /* Ensure stdout is line buffered. This avoids bogus delays
268 of output if stdout is piped through utilities to a terminal. */
269 setvbuf(stdout, NULL, _IOLBF, 0);
272 REQUE(&buffer_head, &buffer_head);
273 for (i = 0; i < 256; i++)
278 /* translit_text: translate characters in a string */
280 translit_text(s, len, from, to)
290 ctab[i] = i; /* restore table to initial state */
292 for (us = (unsigned char *) s; len-- > 0; us++)