Deleted Added
full compact
buf.c (24181) buf.c (27963)
1/* buf.c: This file contains the scratch-file buffer rountines 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.
1/* buf.c: This file contains the scratch-file buffer rountines 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 * $Id: buf.c,v 1.10 1997/02/22 14:03:11 peter Exp $
29 */
27 */
28
30#ifndef lint
29#ifndef lint
30#if 0
31static char * const rcsid = "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp";
31static char * const rcsid = "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp";
32#else
33static char * const rcsid =
34 "$Id: buf.c,v 1.11 1997/03/24 05:45:29 imp Exp $";
35#endif
32#endif /* not lint */
33
34#include <sys/file.h>
35#include <sys/stat.h>
36
37#include "ed.h"
38
39
40FILE *sfp; /* scratch file pointer */
41off_t sfseek; /* scratch file position */
42int seek_write; /* seek before writing */
43line_t buffer_head; /* incore buffer */
44
45/* get_sbuf_line: get a line of text from the scratch file; return pointer
46 to the text */
47char *
48get_sbuf_line(lp)
49 line_t *lp;
50{
51 static char *sfbuf = NULL; /* buffer */
52 static int sfbufsz = 0; /* buffer size */
53
54 int len, ct;
55
56 if (lp == &buffer_head)
57 return NULL;
58 seek_write = 1; /* force seek on write */
59 /* out of position */
60 if (sfseek != lp->seek) {
61 sfseek = lp->seek;
62 if (fseek(sfp, sfseek, SEEK_SET) < 0) {
63 fprintf(stderr, "%s\n", strerror(errno));
64 sprintf(errmsg, "cannot seek temp file");
65 return NULL;
66 }
67 }
68 len = lp->len;
69 REALLOC(sfbuf, sfbufsz, len + 1, NULL);
70 if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) {
71 fprintf(stderr, "%s\n", strerror(errno));
72 sprintf(errmsg, "cannot read temp file");
73 return NULL;
74 }
75 sfseek += len; /* update file position */
76 sfbuf[len] = '\0';
77 return sfbuf;
78}
79
80
81/* put_sbuf_line: write a line of text to the scratch file and add a line node
82 to the editor buffer; return a pointer to the end of the text */
83char *
84put_sbuf_line(cs)
85 char *cs;
86{
87 line_t *lp;
88 int len, ct;
89 char *s;
90
91 if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) {
92 fprintf(stderr, "%s\n", strerror(errno));
93 sprintf(errmsg, "out of memory");
94 return NULL;
95 }
96 /* assert: cs is '\n' terminated */
97 for (s = cs; *s != '\n'; s++)
98 ;
99 if (s - cs >= LINECHARS) {
100 sprintf(errmsg, "line too long");
101 return NULL;
102 }
103 len = s - cs;
104 /* out of position */
105 if (seek_write) {
106 if (fseek(sfp, 0L, SEEK_END) < 0) {
107 fprintf(stderr, "%s\n", strerror(errno));
108 sprintf(errmsg, "cannot seek temp file");
109 return NULL;
110 }
111 sfseek = ftell(sfp);
112 seek_write = 0;
113 }
114 /* assert: SPL1() */
115 if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
116 sfseek = -1;
117 fprintf(stderr, "%s\n", strerror(errno));
118 sprintf(errmsg, "cannot write temp file");
119 return NULL;
120 }
121 lp->len = len;
122 lp->seek = sfseek;
123 add_line_node(lp);
124 sfseek += len; /* update file position */
125 return ++s;
126}
127
128
129/* add_line_node: add a line node in the editor buffer after the current line */
130void
131add_line_node(lp)
132 line_t *lp;
133{
134 line_t *cp;
135
136 cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */
137 INSQUE(lp, cp);
138 addr_last++;
139 current_addr++;
140}
141
142
143/* get_line_node_addr: return line number of pointer */
144long
145get_line_node_addr(lp)
146 line_t *lp;
147{
148 line_t *cp = &buffer_head;
149 long n = 0;
150
151 while (cp != lp && (cp = cp->q_forw) != &buffer_head)
152 n++;
153 if (n && cp == &buffer_head) {
154 sprintf(errmsg, "invalid address");
155 return ERR;
156 }
157 return n;
158}
159
160
161/* get_addressed_line_node: return pointer to a line node in the editor buffer */
162line_t *
163get_addressed_line_node(n)
164 long n;
165{
166 static line_t *lp = &buffer_head;
167 static long on = 0;
168
169 SPL1();
170 if (n > on)
171 if (n <= (on + addr_last) >> 1)
172 for (; on < n; on++)
173 lp = lp->q_forw;
174 else {
175 lp = buffer_head.q_back;
176 for (on = addr_last; on > n; on--)
177 lp = lp->q_back;
178 }
179 else
180 if (n >= on >> 1)
181 for (; on > n; on--)
182 lp = lp->q_back;
183 else {
184 lp = &buffer_head;
185 for (on = 0; on < n; on++)
186 lp = lp->q_forw;
187 }
188 SPL0();
189 return lp;
190}
191
192
193extern int newline_added;
194
195char sfn[15] = ""; /* scratch file name */
196
197/* open_sbuf: open scratch file */
198int
199open_sbuf()
200{
201 int fd = -1;
202 int u;
203
204 isbinary = newline_added = 0;
205 u = umask(077);
206 strcpy(sfn, "/tmp/ed.XXXXXX");
207 if ((fd = mkstemp(sfn)) == -1 ||
208 (sfp = fdopen(fd, "w+")) == NULL) {
209 if (fd != -1)
210 close(fd);
211 perror(sfn);
212 strcpy(errmsg, "cannot open temp file");
213 umask(u);
214 return ERR;
215 }
216 umask(u);
217 return 0;
218}
219
220
221/* close_sbuf: close scratch file */
222int
223close_sbuf()
224{
225 if (sfp) {
226 if (fclose(sfp) < 0) {
227 fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
228 sprintf(errmsg, "cannot close temp file");
229 return ERR;
230 }
231 sfp = NULL;
232 unlink(sfn);
233 }
234 sfseek = seek_write = 0;
235 return 0;
236}
237
238
239/* quit: remove_lines scratch file and exit */
240void
241quit(n)
242 int n;
243{
244 if (sfp) {
245 fclose(sfp);
246 unlink(sfn);
247 }
248 exit(n);
249}
250
251
252unsigned char ctab[256]; /* character translation table */
253
254/* init_buffers: open scratch buffer; initialize line queue */
255void
256init_buffers()
257{
258 int i = 0;
259
260 /* Read stdin one character at a time to avoid i/o contention
261 with shell escapes invoked by nonterminal input, e.g.,
262 ed - <<EOF
263 !cat
264 hello, world
265 EOF */
266 setbuffer(stdin, stdinbuf, 1);
267 if (open_sbuf() < 0)
268 quit(2);
269 REQUE(&buffer_head, &buffer_head);
270 for (i = 0; i < 256; i++)
271 ctab[i] = i;
272}
273
274
275/* translit_text: translate characters in a string */
276char *
277translit_text(s, len, from, to)
278 char *s;
279 int len;
280 int from;
281 int to;
282{
283 static int i = 0;
284
285 unsigned char *us;
286
287 ctab[i] = i; /* restore table to initial state */
288 ctab[i = from] = to;
289 for (us = (unsigned char *) s; len-- > 0; us++)
290 *us = ctab[*us];
291 return s;
292}
36#endif /* not lint */
37
38#include <sys/file.h>
39#include <sys/stat.h>
40
41#include "ed.h"
42
43
44FILE *sfp; /* scratch file pointer */
45off_t sfseek; /* scratch file position */
46int seek_write; /* seek before writing */
47line_t buffer_head; /* incore buffer */
48
49/* get_sbuf_line: get a line of text from the scratch file; return pointer
50 to the text */
51char *
52get_sbuf_line(lp)
53 line_t *lp;
54{
55 static char *sfbuf = NULL; /* buffer */
56 static int sfbufsz = 0; /* buffer size */
57
58 int len, ct;
59
60 if (lp == &buffer_head)
61 return NULL;
62 seek_write = 1; /* force seek on write */
63 /* out of position */
64 if (sfseek != lp->seek) {
65 sfseek = lp->seek;
66 if (fseek(sfp, sfseek, SEEK_SET) < 0) {
67 fprintf(stderr, "%s\n", strerror(errno));
68 sprintf(errmsg, "cannot seek temp file");
69 return NULL;
70 }
71 }
72 len = lp->len;
73 REALLOC(sfbuf, sfbufsz, len + 1, NULL);
74 if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) {
75 fprintf(stderr, "%s\n", strerror(errno));
76 sprintf(errmsg, "cannot read temp file");
77 return NULL;
78 }
79 sfseek += len; /* update file position */
80 sfbuf[len] = '\0';
81 return sfbuf;
82}
83
84
85/* put_sbuf_line: write a line of text to the scratch file and add a line node
86 to the editor buffer; return a pointer to the end of the text */
87char *
88put_sbuf_line(cs)
89 char *cs;
90{
91 line_t *lp;
92 int len, ct;
93 char *s;
94
95 if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) {
96 fprintf(stderr, "%s\n", strerror(errno));
97 sprintf(errmsg, "out of memory");
98 return NULL;
99 }
100 /* assert: cs is '\n' terminated */
101 for (s = cs; *s != '\n'; s++)
102 ;
103 if (s - cs >= LINECHARS) {
104 sprintf(errmsg, "line too long");
105 return NULL;
106 }
107 len = s - cs;
108 /* out of position */
109 if (seek_write) {
110 if (fseek(sfp, 0L, SEEK_END) < 0) {
111 fprintf(stderr, "%s\n", strerror(errno));
112 sprintf(errmsg, "cannot seek temp file");
113 return NULL;
114 }
115 sfseek = ftell(sfp);
116 seek_write = 0;
117 }
118 /* assert: SPL1() */
119 if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
120 sfseek = -1;
121 fprintf(stderr, "%s\n", strerror(errno));
122 sprintf(errmsg, "cannot write temp file");
123 return NULL;
124 }
125 lp->len = len;
126 lp->seek = sfseek;
127 add_line_node(lp);
128 sfseek += len; /* update file position */
129 return ++s;
130}
131
132
133/* add_line_node: add a line node in the editor buffer after the current line */
134void
135add_line_node(lp)
136 line_t *lp;
137{
138 line_t *cp;
139
140 cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */
141 INSQUE(lp, cp);
142 addr_last++;
143 current_addr++;
144}
145
146
147/* get_line_node_addr: return line number of pointer */
148long
149get_line_node_addr(lp)
150 line_t *lp;
151{
152 line_t *cp = &buffer_head;
153 long n = 0;
154
155 while (cp != lp && (cp = cp->q_forw) != &buffer_head)
156 n++;
157 if (n && cp == &buffer_head) {
158 sprintf(errmsg, "invalid address");
159 return ERR;
160 }
161 return n;
162}
163
164
165/* get_addressed_line_node: return pointer to a line node in the editor buffer */
166line_t *
167get_addressed_line_node(n)
168 long n;
169{
170 static line_t *lp = &buffer_head;
171 static long on = 0;
172
173 SPL1();
174 if (n > on)
175 if (n <= (on + addr_last) >> 1)
176 for (; on < n; on++)
177 lp = lp->q_forw;
178 else {
179 lp = buffer_head.q_back;
180 for (on = addr_last; on > n; on--)
181 lp = lp->q_back;
182 }
183 else
184 if (n >= on >> 1)
185 for (; on > n; on--)
186 lp = lp->q_back;
187 else {
188 lp = &buffer_head;
189 for (on = 0; on < n; on++)
190 lp = lp->q_forw;
191 }
192 SPL0();
193 return lp;
194}
195
196
197extern int newline_added;
198
199char sfn[15] = ""; /* scratch file name */
200
201/* open_sbuf: open scratch file */
202int
203open_sbuf()
204{
205 int fd = -1;
206 int u;
207
208 isbinary = newline_added = 0;
209 u = umask(077);
210 strcpy(sfn, "/tmp/ed.XXXXXX");
211 if ((fd = mkstemp(sfn)) == -1 ||
212 (sfp = fdopen(fd, "w+")) == NULL) {
213 if (fd != -1)
214 close(fd);
215 perror(sfn);
216 strcpy(errmsg, "cannot open temp file");
217 umask(u);
218 return ERR;
219 }
220 umask(u);
221 return 0;
222}
223
224
225/* close_sbuf: close scratch file */
226int
227close_sbuf()
228{
229 if (sfp) {
230 if (fclose(sfp) < 0) {
231 fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
232 sprintf(errmsg, "cannot close temp file");
233 return ERR;
234 }
235 sfp = NULL;
236 unlink(sfn);
237 }
238 sfseek = seek_write = 0;
239 return 0;
240}
241
242
243/* quit: remove_lines scratch file and exit */
244void
245quit(n)
246 int n;
247{
248 if (sfp) {
249 fclose(sfp);
250 unlink(sfn);
251 }
252 exit(n);
253}
254
255
256unsigned char ctab[256]; /* character translation table */
257
258/* init_buffers: open scratch buffer; initialize line queue */
259void
260init_buffers()
261{
262 int i = 0;
263
264 /* Read stdin one character at a time to avoid i/o contention
265 with shell escapes invoked by nonterminal input, e.g.,
266 ed - <<EOF
267 !cat
268 hello, world
269 EOF */
270 setbuffer(stdin, stdinbuf, 1);
271 if (open_sbuf() < 0)
272 quit(2);
273 REQUE(&buffer_head, &buffer_head);
274 for (i = 0; i < 256; i++)
275 ctab[i] = i;
276}
277
278
279/* translit_text: translate characters in a string */
280char *
281translit_text(s, len, from, to)
282 char *s;
283 int len;
284 int from;
285 int to;
286{
287 static int i = 0;
288
289 unsigned char *us;
290
291 ctab[i] = i; /* restore table to initial state */
292 ctab[i = from] = to;
293 for (us = (unsigned char *) s; len-- > 0; us++)
294 *us = ctab[*us];
295 return s;
296}