1 /* $NetBSD: buf.c,v 1.25 2005/06/26 19:10:49 christos Exp $ */
3 /* buf.c: This file contains the scratch-file buffer routines for the
6 * Copyright (c) 1993 Andrew Moore, Talke Studio.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
31 #include <sys/cdefs.h>
34 static char *rcsid
= "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp";
36 __RCSID("$NetBSD: buf.c,v 1.25 2005/06/26 19:10:49 christos Exp $");
50 FILE *sfp
; /* scratch file pointer */
51 off_t sfseek
; /* scratch file position */
52 int seek_write
; /* seek before writing */
53 line_t buffer_head
; /* incore buffer */
55 /* get_sbuf_line: get a line of text from the scratch file; return pointer
58 get_sbuf_line(line_t
*lp
)
60 static char *sfbuf
= NULL
; /* buffer */
61 static int sfbufsz
= 0; /* buffer size */
65 if (lp
== &buffer_head
)
67 seek_write
= 1; /* force seek on write */
69 if (sfseek
!= lp
->seek
) {
71 if (fseek(sfp
, sfseek
, SEEK_SET
) < 0) {
72 fprintf(stderr
, "%s\n", strerror(errno
));
73 sprintf(errmsg
, "cannot seek temp file");
78 REALLOC(sfbuf
, sfbufsz
, len
+ 1, NULL
);
79 if ((ct
= fread(sfbuf
, sizeof(char), len
, sfp
)) < 0 || ct
!= len
) {
80 fprintf(stderr
, "%s\n", strerror(errno
));
81 sprintf(errmsg
, "cannot read temp file");
84 sfseek
+= len
; /* update file position */
90 /* put_sbuf_line: write a line of text to the scratch file and add a line node
91 to the editor buffer; return a pointer to the end of the text */
93 put_sbuf_line(char *cs
)
99 if ((lp
= (line_t
*) malloc(sizeof(line_t
))) == NULL
) {
100 fprintf(stderr
, "%s\n", strerror(errno
));
101 sprintf(errmsg
, "out of memory");
104 /* assert: cs is '\n' terminated */
105 for (s
= cs
; *s
!= '\n'; s
++)
107 if (s
- cs
>= LINECHARS
) {
108 sprintf(errmsg
, "line too long");
113 /* out of position */
115 if (fseek(sfp
, 0L, SEEK_END
) < 0) {
116 fprintf(stderr
, "%s\n", strerror(errno
));
117 sprintf(errmsg
, "cannot seek temp file");
125 if ((ct
= fwrite(cs
, sizeof(char), len
, sfp
)) < 0 || ct
!= len
) {
127 fprintf(stderr
, "%s\n", strerror(errno
));
128 sprintf(errmsg
, "cannot write temp file");
135 sfseek
+= len
; /* update file position */
140 /* add_line_node: add a line node in the editor buffer after the current line */
142 add_line_node(line_t
*lp
)
146 cp
= get_addressed_line_node(current_addr
); /* this get_addressed_line_node last! */
153 /* get_line_node_addr: return line number of pointer */
155 get_line_node_addr(line_t
*lp
)
157 line_t
*cp
= &buffer_head
;
160 while (cp
!= lp
&& (cp
= cp
->q_forw
) != &buffer_head
)
162 if (n
&& cp
== &buffer_head
) {
163 sprintf(errmsg
, "invalid address");
170 /* get_addressed_line_node: return pointer to a line node in the editor buffer */
172 get_addressed_line_node(long n
)
174 static line_t
*lp
= &buffer_head
;
179 if (n
<= (on
+ addr_last
) >> 1) {
183 lp
= buffer_head
.q_back
;
184 for (on
= addr_last
; on
> n
; on
--)
193 for (on
= 0; on
< n
; on
++)
202 char *sfn
= NULL
; /* scratch file name */
204 /* open_sbuf: open scratch file */
212 isbinary
= newline_added
= 0;
216 if ((tmp
= getenv("TMPDIR")) == NULL
)
219 if ((s
= strlen(tmp
)) == 0 || tmp
[s
- 1] == '/')
220 (void)asprintf(&sfn
, "%sed.XXXXXX", tmp
);
222 (void)asprintf(&sfn
, "%s/ed.XXXXXX", tmp
);
225 sprintf(errmsg
, "could not allocate memory");
231 if ((fd
= mkstemp(sfn
)) == -1 || (sfp
= fdopen(fd
, "w+")) == NULL
) {
235 sprintf(errmsg
, "cannot open temp file");
244 /* close_sbuf: close scratch file */
249 if (fclose(sfp
) < 0) {
250 fprintf(stderr
, "%s: %s\n", sfn
, strerror(errno
));
251 sprintf(errmsg
, "cannot close temp file");
261 sfseek
= seek_write
= 0;
266 /* quit: remove_lines scratch file and exit */
283 unsigned char ctab
[256]; /* character translation table */
285 /* init_buffers: open scratch buffer; initialize line queue */
291 /* Read stdin one character at a time to avoid i/o contention
292 with shell escapes invoked by nonterminal input, e.g.,
297 setbuffer(stdin
, stdinbuf
, 1);
300 REQUE(&buffer_head
, &buffer_head
);
301 for (i
= 0; i
< 256; i
++)
306 /* translit_text: translate characters in a string */
308 translit_text(char *s
, int len
, int from
, int to
)
314 ctab
[i
] = i
; /* restore table to initial state */
316 for (us
= (unsigned char *) s
; len
-- > 0; us
++)