]> git.cameronkatri.com Git - apple_cmds.git/blob - text_cmds/ed/buf.c
diskdev_cmds: use libiosexec
[apple_cmds.git] / text_cmds / ed / buf.c
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: src/bin/ed/buf.c,v 1.22 2002/06/30 05:13:53 obrien Exp $");
31
32 #include <sys/file.h>
33 #include <sys/stat.h>
34
35 #include "ed.h"
36
37
38 FILE *sfp; /* scratch file pointer */
39 off_t sfseek; /* scratch file position */
40 int seek_write; /* seek before writing */
41 line_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 */
45 char *
46 get_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 */
80 const char *
81 put_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 return NULL;
98 }
99 len = s - cs;
100 /* out of position */
101 if (seek_write) {
102 if (fseeko(sfp, (off_t)0, SEEK_END) < 0) {
103 fprintf(stderr, "%s\n", strerror(errno));
104 errmsg = "cannot seek temp file";
105 return NULL;
106 }
107 sfseek = ftello(sfp);
108 seek_write = 0;
109 }
110 /* assert: SPL1() */
111 if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
112 sfseek = -1;
113 fprintf(stderr, "%s\n", strerror(errno));
114 errmsg = "cannot write temp file";
115 return NULL;
116 }
117 lp->len = len;
118 lp->seek = sfseek;
119 add_line_node(lp);
120 sfseek += len; /* update file position */
121 return ++s;
122 }
123
124
125 /* add_line_node: add a line node in the editor buffer after the current line */
126 void
127 add_line_node(line_t *lp)
128 {
129 line_t *cp;
130
131 cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */
132 INSQUE(lp, cp);
133 addr_last++;
134 current_addr++;
135 }
136
137
138 /* get_line_node_addr: return line number of pointer */
139 long
140 get_line_node_addr(line_t *lp)
141 {
142 line_t *cp = &buffer_head;
143 long n = 0;
144
145 while (cp != lp && (cp = cp->q_forw) != &buffer_head)
146 n++;
147 if (n && cp == &buffer_head) {
148 errmsg = "invalid address";
149 return ERR;
150 }
151 return n;
152 }
153
154
155 /* get_addressed_line_node: return pointer to a line node in the editor buffer */
156 line_t *
157 get_addressed_line_node(long n)
158 {
159 static line_t *lp = &buffer_head;
160 static long on = 0;
161
162 SPL1();
163 if (n > on)
164 if (n <= (on + addr_last) >> 1)
165 for (; on < n; on++)
166 lp = lp->q_forw;
167 else {
168 lp = buffer_head.q_back;
169 for (on = addr_last; on > n; on--)
170 lp = lp->q_back;
171 }
172 else
173 if (n >= on >> 1)
174 for (; on > n; on--)
175 lp = lp->q_back;
176 else {
177 lp = &buffer_head;
178 for (on = 0; on < n; on++)
179 lp = lp->q_forw;
180 }
181 SPL0();
182 return lp;
183 }
184
185
186 extern int newline_added;
187
188 char sfn[15] = ""; /* scratch file name */
189
190 /* open_sbuf: open scratch file */
191 int
192 open_sbuf(void)
193 {
194 int fd;
195 int u;
196
197 isbinary = newline_added = 0;
198 u = umask(077);
199 strcpy(sfn, "/tmp/ed.XXXXXX");
200 if ((fd = mkstemp(sfn)) == -1 ||
201 (sfp = fdopen(fd, "w+")) == NULL) {
202 if (fd != -1)
203 close(fd);
204 perror(sfn);
205 errmsg = "cannot open temp file";
206 umask(u);
207 return ERR;
208 }
209 umask(u);
210 return 0;
211 }
212
213
214 /* close_sbuf: close scratch file */
215 int
216 close_sbuf(void)
217 {
218 if (sfp) {
219 if (fclose(sfp) < 0) {
220 fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
221 errmsg = "cannot close temp file";
222 return ERR;
223 }
224 sfp = NULL;
225 unlink(sfn);
226 }
227 sfseek = seek_write = 0;
228 return 0;
229 }
230
231
232 /* quit: remove_lines scratch file and exit */
233 void
234 quit(int n)
235 {
236 if (sfp) {
237 fclose(sfp);
238 unlink(sfn);
239 }
240 exit(n);
241 }
242
243
244 unsigned char ctab[256]; /* character translation table */
245
246 /* init_buffers: open scratch buffer; initialize line queue */
247 void
248 init_buffers(void)
249 {
250 int i = 0;
251
252 /* Read stdin one character at a time to avoid i/o contention
253 with shell escapes invoked by nonterminal input, e.g.,
254 ed - <<EOF
255 !cat
256 hello, world
257 EOF */
258 setbuffer(stdin, stdinbuf, 1);
259
260 /* Ensure stdout is line buffered. This avoids bogus delays
261 of output if stdout is piped through utilities to a terminal. */
262 setvbuf(stdout, NULL, _IOLBF, 0);
263 if (open_sbuf() < 0)
264 quit(2);
265 REQUE(&buffer_head, &buffer_head);
266 for (i = 0; i < 256; i++)
267 ctab[i] = i;
268 }
269
270
271 /* translit_text: translate characters in a string */
272 char *
273 translit_text(char *s, int len, int from, int to)
274 {
275 static int i = 0;
276
277 unsigned char *us;
278
279 ctab[i] = i; /* restore table to initial state */
280 ctab[i = from] = to;
281 for (us = (unsigned char *) s; len-- > 0; us++)
282 *us = ctab[*us];
283 return s;
284 }