buf.c revision 1057
116Salm/* buf.c: This file contains the scratch-file buffer rountines for the 216Salm ed line editor. */ 316Salm/*- 41057Salm * Copyright (c) 1993 Andrew Moore, Talke Studio. 516Salm * All rights reserved. 616Salm * 716Salm * Redistribution and use in source and binary forms, with or without 816Salm * modification, are permitted provided that the following conditions 916Salm * are met: 1016Salm * 1. Redistributions of source code must retain the above copyright 1116Salm * notice, this list of conditions and the following disclaimer. 1216Salm * 2. Redistributions in binary form must reproduce the above copyright 1316Salm * notice, this list of conditions and the following disclaimer in the 1416Salm * documentation and/or other materials provided with the distribution. 1516Salm * 161057Salm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1716Salm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1816Salm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191057Salm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2016Salm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2116Salm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2216Salm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2316Salm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2416Salm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2516Salm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2616Salm * SUCH DAMAGE. 2716Salm */ 2816Salm#ifndef lint 291057Salmstatic char *rcsid = "@(#)$Id: buf.c,v 1.3 1993/12/14 16:19:56 alm Exp $"; 3016Salm#endif /* not lint */ 3116Salm 3216Salm#include <sys/file.h> 3316Salm 3416Salm#include "ed.h" 3516Salm 3616Salm 3716SalmFILE *sfp; /* scratch file pointer */ 3816Salmoff_t sfseek; /* scratch file position */ 3916Salmint seek_write; /* seek before writing */ 401057Salmline_t buffer_head; /* incore buffer */ 4116Salm 421057Salm/* get_sbuf_line: get a line of text from the scratch file; return pointer 4316Salm to the text */ 4416Salmchar * 451057Salmget_sbuf_line(lp) 4616Salm line_t *lp; 4716Salm{ 481057Salm static char *sfbuf = NULL; /* buffer */ 491057Salm static int sfbufsz = 0; /* buffer size */ 501057Salm 5116Salm int len, ct; 5216Salm 531057Salm if (lp == &buffer_head) 5416Salm return NULL; 5516Salm seek_write = 1; /* force seek on write */ 5616Salm /* out of position */ 5716Salm if (sfseek != lp->seek) { 5816Salm sfseek = lp->seek; 5916Salm if (fseek(sfp, sfseek, SEEK_SET) < 0) { 6016Salm fprintf(stderr, "%s\n", strerror(errno)); 6116Salm sprintf(errmsg, "cannot seek temp file"); 6216Salm return NULL; 6316Salm } 6416Salm } 651057Salm len = lp->len; 661057Salm REALLOC(sfbuf, sfbufsz, len + 1, NULL); 6716Salm if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) { 6816Salm fprintf(stderr, "%s\n", strerror(errno)); 6916Salm sprintf(errmsg, "cannot read temp file"); 7016Salm return NULL; 7116Salm } 7216Salm sfseek += len; /* update file position */ 7316Salm sfbuf[len] = '\0'; 7416Salm return sfbuf; 7516Salm} 7616Salm 7716Salm 781057Salm/* put_sbuf_line: write a line of text to the scratch file and add a line node 7916Salm to the editor buffer; return a pointer to the end of the text */ 8016Salmchar * 811057Salmput_sbuf_line(cs) 8216Salm char *cs; 8316Salm{ 8416Salm line_t *lp; 8516Salm int len, ct; 8616Salm char *s; 8716Salm 8816Salm if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) { 8916Salm fprintf(stderr, "%s\n", strerror(errno)); 9016Salm sprintf(errmsg, "out of memory"); 9116Salm return NULL; 9216Salm } 9316Salm /* assert: cs is '\n' terminated */ 9416Salm for (s = cs; *s != '\n'; s++) 9516Salm ; 9616Salm if (s - cs >= LINECHARS) { 9716Salm sprintf(errmsg, "line too long"); 9816Salm return NULL; 9916Salm } 1001057Salm len = s - cs; 10116Salm /* out of position */ 10216Salm if (seek_write) { 10316Salm if (fseek(sfp, 0L, SEEK_END) < 0) { 10416Salm fprintf(stderr, "%s\n", strerror(errno)); 10516Salm sprintf(errmsg, "cannot seek temp file"); 10616Salm return NULL; 10716Salm } 10816Salm sfseek = ftell(sfp); 10916Salm seek_write = 0; 11016Salm } 1111057Salm /* assert: SPL1() */ 11216Salm if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) { 11316Salm sfseek = -1; 11416Salm fprintf(stderr, "%s\n", strerror(errno)); 11516Salm sprintf(errmsg, "cannot write temp file"); 11616Salm return NULL; 11716Salm } 11816Salm lp->len = len; 11916Salm lp->seek = sfseek; 1201057Salm add_line_node(lp); 12116Salm sfseek += len; /* update file position */ 12216Salm return ++s; 12316Salm} 12416Salm 12516Salm 1261057Salm/* add_line_node: add a line node in the editor buffer after the current line */ 12716Salmvoid 1281057Salmadd_line_node(lp) 12916Salm line_t *lp; 13016Salm{ 13116Salm line_t *cp; 13216Salm 1331057Salm cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */ 1341057Salm insque(lp, cp); 1351057Salm addr_last++; 1361057Salm current_addr++; 13716Salm} 13816Salm 13916Salm 1401057Salm/* get_line_node_addr: return line number of pointer */ 14116Salmlong 1421057Salmget_line_node_addr(lp) 14316Salm line_t *lp; 14416Salm{ 1451057Salm line_t *cp = &buffer_head; 14616Salm long n = 0; 14716Salm 1481057Salm while (cp != lp && (cp = cp->q_forw) != &buffer_head) 14916Salm n++; 1501057Salm if (n && cp == &buffer_head) { 15149Salm sprintf(errmsg, "invalid address"); 15249Salm return ERR; 15349Salm } 15449Salm return n; 15516Salm} 15616Salm 15716Salm 1581057Salm/* get_addressed_line_node: return pointer to a line node in the editor buffer */ 15916Salmline_t * 1601057Salmget_addressed_line_node(n) 16116Salm long n; 16216Salm{ 1631057Salm static line_t *lp = &buffer_head; 16416Salm static long on = 0; 16516Salm 1661057Salm SPL1(); 16716Salm if (n > on) 1681057Salm if (n <= (on + addr_last) >> 1) 16916Salm for (; on < n; on++) 1701057Salm lp = lp->q_forw; 17116Salm else { 1721057Salm lp = buffer_head.q_back; 1731057Salm for (on = addr_last; on > n; on--) 1741057Salm lp = lp->q_back; 17516Salm } 17616Salm else 17716Salm if (n >= on >> 1) 17816Salm for (; on > n; on--) 1791057Salm lp = lp->q_back; 18016Salm else { 1811057Salm lp = &buffer_head; 18216Salm for (on = 0; on < n; on++) 1831057Salm lp = lp->q_forw; 18416Salm } 1851057Salm SPL0(); 18616Salm return lp; 18716Salm} 18816Salm 18916Salm 1901057Salmextern int newline_added; 1911057Salm 19216Salmchar sfn[15] = ""; /* scratch file name */ 19316Salm 1941057Salm/* open_sbuf: open scratch file */ 1951057Salmint 1961057Salmopen_sbuf() 19716Salm{ 1981057Salm isbinary = newline_added = 0; 19916Salm strcpy(sfn, "/tmp/ed.XXXXXX"); 20016Salm if (mktemp(sfn) == NULL || (sfp = fopen(sfn, "w+")) == NULL) { 20116Salm fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); 20216Salm sprintf(errmsg, "cannot open temp file"); 20316Salm return ERR; 20416Salm } 20516Salm return 0; 20616Salm} 20716Salm 20816Salm 2091057Salm/* close_sbuf: close scratch file */ 2101057Salmint 2111057Salmclose_sbuf() 21216Salm{ 21316Salm if (sfp) { 21416Salm if (fclose(sfp) < 0) { 21516Salm fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); 21616Salm sprintf(errmsg, "cannot close temp file"); 21716Salm return ERR; 21816Salm } 21916Salm sfp = NULL; 22016Salm unlink(sfn); 22116Salm } 22216Salm sfseek = seek_write = 0; 22316Salm return 0; 22416Salm} 22516Salm 22616Salm 2271057Salm/* quit: remove_lines scratch file and exit */ 22816Salmvoid 22916Salmquit(n) 23016Salm int n; 23116Salm{ 23216Salm if (sfp) { 23316Salm fclose(sfp); 23416Salm unlink(sfn); 23516Salm } 23616Salm exit(n); 23716Salm} 23887Salm 23987Salm 24087Salmunsigned char ctab[256]; /* character translation table */ 24187Salm 2421057Salm/* init_buffers: open scratch buffer; initialize line queue */ 24387Salmvoid 2441057Salminit_buffers() 24587Salm{ 24687Salm int i = 0; 24787Salm 2481057Salm /* Read stdin one character at a time to avoid i/o contention 2491057Salm with shell escapes invoked by nonterminal input, e.g., 2501057Salm ed - <<EOF 2511057Salm !cat 2521057Salm hello, world 2531057Salm EOF */ 2541057Salm setbuffer(stdin, stdinbuf, 1); 2551057Salm if (open_sbuf() < 0) 25687Salm quit(2); 2571057Salm REQUE(&buffer_head, &buffer_head); 25887Salm for (i = 0; i < 256; i++) 25987Salm ctab[i] = i; 26087Salm} 26187Salm 26287Salm 2631057Salm/* translit_text: translate characters in a string */ 26487Salmchar * 2651057Salmtranslit_text(s, len, from, to) 26687Salm char *s; 26787Salm int len; 26887Salm int from; 26987Salm int to; 27087Salm{ 27187Salm static int i = 0; 27287Salm 27387Salm unsigned char *us; 27487Salm 27587Salm ctab[i] = i; /* restore table to initial state */ 27687Salm ctab[i = from] = to; 27787Salm for (us = (unsigned char *) s; len-- > 0; us++) 27887Salm *us = ctab[*us]; 27987Salm return s; 28087Salm} 281