xref: /386bsd/usr/src/bin/ed/buf.c (revision a2142627)
1 /* buf.c: This file contains the scratch-file buffer rountines for the
2    ed line editor. */
3 /*-
4  * Copyright (c) 1992 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Rodney Ruddock of the University of Guelph.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  */
38 
39 #ifndef lint
40 static char sccsid[] = "@(#)buf.c	5.5 (Berkeley) 3/28/93";
41 #endif /* not lint */
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/file.h>
47 #include <unistd.h>
48 
49 #include "ed.h"
50 
51 extern char errmsg[];
52 
53 FILE *sfp;				/* scratch file pointer */
54 char *sfbuf = NULL;			/* scratch file input buffer */
55 int sfbufsz = 0;			/* scratch file input buffer size */
56 off_t sfseek;				/* scratch file position */
57 int seek_write;				/* seek before writing */
58 line_t line0;				/* initial node of line queue */
59 
60 /* gettxt: get a line of text from the scratch file; return pointer
61    to the text */
62 char *
gettxt(lp)63 gettxt(lp)
64 	line_t *lp;
65 {
66 	int len, ct;
67 
68 	if (lp == &line0)
69 		return NULL;
70 	seek_write = 1;				/* force seek on write */
71 	/* out of position */
72 	if (sfseek != lp->seek) {
73 		sfseek = lp->seek;
74 		if (fseek(sfp, sfseek, SEEK_SET) < 0) {
75 			fprintf(stderr, "%s\n", strerror(errno));
76 			sprintf(errmsg, "cannot seek temp file");
77 			return NULL;
78 		}
79 	}
80 	len = lp->len & ~ACTV;
81 	CKBUF(sfbuf, sfbufsz, len + 1, NULL);
82 	if ((ct = fread(sfbuf, sizeof(char), len, sfp)) <  0 || ct != len) {
83 		fprintf(stderr, "%s\n", strerror(errno));
84 		sprintf(errmsg, "cannot read temp file");
85 		return NULL;
86 	}
87 	sfseek += len;				/* update file position */
88 	sfbuf[len] = '\0';
89 	return sfbuf;
90 }
91 
92 
93 extern long curln;
94 extern long lastln;
95 
96 /* puttxt: write a line of text to the scratch file and add a line node
97    to the editor buffer;  return a pointer to the end of the text */
98 char *
puttxt(cs)99 puttxt(cs)
100 	char *cs;
101 {
102 	line_t *lp;
103 	int len, ct;
104 	char *s;
105 
106 	if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) {
107 		fprintf(stderr, "%s\n", strerror(errno));
108 		sprintf(errmsg, "out of memory");
109 		return NULL;
110 	}
111 	/* assert: cs is '\n' terminated */
112 	for (s = cs; *s != '\n'; s++)
113 		;
114 	if (s - cs >= LINECHARS) {
115 		sprintf(errmsg, "line too long");
116 		return NULL;
117 	}
118 	len = (s - cs) & ~ACTV;
119 	/* out of position */
120 	if (seek_write) {
121 		if (fseek(sfp, 0L, SEEK_END) < 0) {
122 			fprintf(stderr, "%s\n", strerror(errno));
123 			sprintf(errmsg, "cannot seek temp file");
124 			return NULL;
125 		}
126 		sfseek = ftell(sfp);
127 		seek_write = 0;
128 	}
129 	/* assert: spl1() */
130 	if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
131 		sfseek = -1;
132 		fprintf(stderr, "%s\n", strerror(errno));
133 		sprintf(errmsg, "cannot write temp file");
134 		return NULL;
135 	}
136 	lp->len = len;
137 	lp->seek  = sfseek;
138 	lpqueue(lp);
139 	sfseek += len;			/* update file position */
140 	return ++s;
141 }
142 
143 
144 /* lpqueue: add a line node in the editor buffer after the current line */
145 void
lpqueue(lp)146 lpqueue(lp)
147 	line_t *lp;
148 {
149 	line_t *cp;
150 
151 	cp = getlp(curln);				/* this getlp last! */
152 	insqueue(lp, cp);
153 	lastln++;
154 	curln++;
155 }
156 
157 
158 /* getaddr: return line number of pointer */
159 long
getaddr(lp)160 getaddr(lp)
161 	line_t *lp;
162 {
163 	line_t *cp = &line0;
164 	long n = 0;
165 
166 	while (cp != lp && (cp = cp->next) != &line0)
167 		n++;
168 	if (n && cp == &line0) {
169 		sprintf(errmsg, "invalid address");
170 		return ERR;
171 	 }
172 	 return n;
173 }
174 
175 
176 /* getlp: return pointer to a line node in the editor buffer */
177 line_t *
getlp(n)178 getlp(n)
179 	long n;
180 {
181 	static line_t *lp = &line0;
182 	static long on = 0;
183 
184 	spl1();
185 	if (n > on)
186 		if (n <= (on + lastln) >> 1)
187 			for (; on < n; on++)
188 				lp = lp->next;
189 		else {
190 			lp = line0.prev;
191 			for (on = lastln; on > n; on--)
192 				lp = lp->prev;
193 		}
194 	else
195 		if (n >= on >> 1)
196 			for (; on > n; on--)
197 				lp = lp->prev;
198 		else {
199 			lp = &line0;
200 			for (on = 0; on < n; on++)
201 				lp = lp->next;
202 		}
203 	spl0();
204 	return lp;
205 }
206 
207 
208 char sfn[15] = "";				/* scratch file name */
209 
210 /* sbopen: open scratch file */
sbopen()211 sbopen()
212 {
213 	strcpy(sfn, "/tmp/ed.XXXXXX");
214 	if (mktemp(sfn) == NULL || (sfp = fopen(sfn, "w+")) == NULL) {
215 		fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
216 		sprintf(errmsg, "cannot open temp file");
217 		return ERR;
218 	}
219 	return 0;
220 }
221 
222 
223 /* sbclose: close scratch file */
sbclose()224 sbclose()
225 {
226 	if (sfp) {
227 		if (fclose(sfp) < 0) {
228 			fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
229 			sprintf(errmsg, "cannot close temp file");
230 			return ERR;
231 		}
232 		sfp = NULL;
233 		unlink(sfn);
234 	}
235 	sfseek = seek_write = 0;
236 	return 0;
237 }
238 
239 
240 /* quit: remove scratch file and exit */
241 void
quit(n)242 quit(n)
243 	int n;
244 {
245 	if (sfp) {
246 		fclose(sfp);
247 		unlink(sfn);
248 	}
249 	exit(n);
250 }
251 
252 
253 unsigned char ctab[256];		/* character translation table */
254 
255 /* init_buf: open scratch buffer; initialize line queue */
256 void
init_buf()257 init_buf()
258 {
259 	int i = 0;
260 
261 	if (sbopen() < 0)
262 		quit(2);
263 	requeue(&line0, &line0);
264 	for (i = 0; i < 256; i++)
265 		ctab[i] = i;
266 }
267 
268 
269 /* translit: translate characters in a string */
270 char *
translit(s,len,from,to)271 translit(s, len, from, to)
272 	char *s;
273 	int len;
274 	int from;
275 	int to;
276 {
277 	static int i = 0;
278 
279 	unsigned char *us;
280 
281 	ctab[i] = i;			/* restore table to initial state */
282 	ctab[i = from] = to;
283 	for (us = (unsigned char *) s; len-- > 0; us++)
284 		*us = ctab[*us];
285 	return s;
286 }
287