buf.c revision 20420
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. 273044Sdg * 2820420Ssteve * $Id: buf.c,v 1.7 1995/05/30 00:06:43 rgrimes Exp $ 2916Salm */ 3016Salm#ifndef lint 3120420Sstevestatic char * const rcsid = "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp"; 3216Salm#endif /* not lint */ 3316Salm 3416Salm#include <sys/file.h> 351297Salm#include <sys/stat.h> 3616Salm 3716Salm#include "ed.h" 3816Salm 3916Salm 4016SalmFILE *sfp; /* scratch file pointer */ 4116Salmoff_t sfseek; /* scratch file position */ 4216Salmint seek_write; /* seek before writing */ 431057Salmline_t buffer_head; /* incore buffer */ 4416Salm 451057Salm/* get_sbuf_line: get a line of text from the scratch file; return pointer 4616Salm to the text */ 4716Salmchar * 481057Salmget_sbuf_line(lp) 4916Salm line_t *lp; 5016Salm{ 511057Salm static char *sfbuf = NULL; /* buffer */ 521057Salm static int sfbufsz = 0; /* buffer size */ 531057Salm 5416Salm int len, ct; 5516Salm 561057Salm if (lp == &buffer_head) 5716Salm return NULL; 5816Salm seek_write = 1; /* force seek on write */ 5916Salm /* out of position */ 6016Salm if (sfseek != lp->seek) { 6116Salm sfseek = lp->seek; 6216Salm if (fseek(sfp, sfseek, SEEK_SET) < 0) { 6316Salm fprintf(stderr, "%s\n", strerror(errno)); 6416Salm sprintf(errmsg, "cannot seek temp file"); 6516Salm return NULL; 6616Salm } 6716Salm } 681057Salm len = lp->len; 691057Salm REALLOC(sfbuf, sfbufsz, len + 1, NULL); 7016Salm if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) { 7116Salm fprintf(stderr, "%s\n", strerror(errno)); 7216Salm sprintf(errmsg, "cannot read temp file"); 7316Salm return NULL; 7416Salm } 7516Salm sfseek += len; /* update file position */ 7616Salm sfbuf[len] = '\0'; 7716Salm return sfbuf; 7816Salm} 7916Salm 8016Salm 811057Salm/* put_sbuf_line: write a line of text to the scratch file and add a line node 8216Salm to the editor buffer; return a pointer to the end of the text */ 8316Salmchar * 841057Salmput_sbuf_line(cs) 8516Salm char *cs; 8616Salm{ 8716Salm line_t *lp; 8816Salm int len, ct; 8916Salm char *s; 9016Salm 9116Salm if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) { 9216Salm fprintf(stderr, "%s\n", strerror(errno)); 9316Salm sprintf(errmsg, "out of memory"); 9416Salm return NULL; 9516Salm } 9616Salm /* assert: cs is '\n' terminated */ 9716Salm for (s = cs; *s != '\n'; s++) 9816Salm ; 9916Salm if (s - cs >= LINECHARS) { 10016Salm sprintf(errmsg, "line too long"); 10116Salm return NULL; 10216Salm } 1031057Salm len = s - cs; 10416Salm /* out of position */ 10516Salm if (seek_write) { 10616Salm if (fseek(sfp, 0L, SEEK_END) < 0) { 10716Salm fprintf(stderr, "%s\n", strerror(errno)); 10816Salm sprintf(errmsg, "cannot seek temp file"); 10916Salm return NULL; 11016Salm } 11116Salm sfseek = ftell(sfp); 11216Salm seek_write = 0; 11316Salm } 1141057Salm /* assert: SPL1() */ 11516Salm if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) { 11616Salm sfseek = -1; 11716Salm fprintf(stderr, "%s\n", strerror(errno)); 11816Salm sprintf(errmsg, "cannot write temp file"); 11916Salm return NULL; 12016Salm } 12116Salm lp->len = len; 12216Salm lp->seek = sfseek; 1231057Salm add_line_node(lp); 12416Salm sfseek += len; /* update file position */ 12516Salm return ++s; 12616Salm} 12716Salm 12816Salm 1291057Salm/* add_line_node: add a line node in the editor buffer after the current line */ 13016Salmvoid 1311057Salmadd_line_node(lp) 13216Salm line_t *lp; 13316Salm{ 13416Salm line_t *cp; 13516Salm 1361057Salm cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */ 1371297Salm INSQUE(lp, cp); 1381057Salm addr_last++; 1391057Salm current_addr++; 14016Salm} 14116Salm 14216Salm 1431057Salm/* get_line_node_addr: return line number of pointer */ 14416Salmlong 1451057Salmget_line_node_addr(lp) 14616Salm line_t *lp; 14716Salm{ 1481057Salm line_t *cp = &buffer_head; 14916Salm long n = 0; 15016Salm 1511057Salm while (cp != lp && (cp = cp->q_forw) != &buffer_head) 15216Salm n++; 1531057Salm if (n && cp == &buffer_head) { 15449Salm sprintf(errmsg, "invalid address"); 15549Salm return ERR; 15649Salm } 15749Salm return n; 15816Salm} 15916Salm 16016Salm 1611057Salm/* get_addressed_line_node: return pointer to a line node in the editor buffer */ 16216Salmline_t * 1631057Salmget_addressed_line_node(n) 16416Salm long n; 16516Salm{ 1661057Salm static line_t *lp = &buffer_head; 16716Salm static long on = 0; 16816Salm 1691057Salm SPL1(); 17016Salm if (n > on) 1711057Salm if (n <= (on + addr_last) >> 1) 17216Salm for (; on < n; on++) 1731057Salm lp = lp->q_forw; 17416Salm else { 1751057Salm lp = buffer_head.q_back; 1761057Salm for (on = addr_last; on > n; on--) 1771057Salm lp = lp->q_back; 17816Salm } 17916Salm else 18016Salm if (n >= on >> 1) 18116Salm for (; on > n; on--) 1821057Salm lp = lp->q_back; 18316Salm else { 1841057Salm lp = &buffer_head; 18516Salm for (on = 0; on < n; on++) 1861057Salm lp = lp->q_forw; 18716Salm } 1881057Salm SPL0(); 18916Salm return lp; 19016Salm} 19116Salm 19216Salm 1931057Salmextern int newline_added; 1941057Salm 19516Salmchar sfn[15] = ""; /* scratch file name */ 19616Salm 1971057Salm/* open_sbuf: open scratch file */ 1981057Salmint 1991057Salmopen_sbuf() 20016Salm{ 2011297Salm int u; 2021297Salm 2031057Salm isbinary = newline_added = 0; 2041297Salm u = umask(077); 20516Salm strcpy(sfn, "/tmp/ed.XXXXXX"); 20616Salm if (mktemp(sfn) == NULL || (sfp = fopen(sfn, "w+")) == NULL) { 20716Salm fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); 20816Salm sprintf(errmsg, "cannot open temp file"); 2091297Salm umask(u); 21016Salm return ERR; 21116Salm } 2121297Salm umask(u); 21316Salm return 0; 21416Salm} 21516Salm 21616Salm 2171057Salm/* close_sbuf: close scratch file */ 2181057Salmint 2191057Salmclose_sbuf() 22016Salm{ 22116Salm if (sfp) { 22216Salm if (fclose(sfp) < 0) { 22316Salm fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); 22416Salm sprintf(errmsg, "cannot close temp file"); 22516Salm return ERR; 22616Salm } 22716Salm sfp = NULL; 22816Salm unlink(sfn); 22916Salm } 23016Salm sfseek = seek_write = 0; 23116Salm return 0; 23216Salm} 23316Salm 23416Salm 2351057Salm/* quit: remove_lines scratch file and exit */ 23616Salmvoid 23716Salmquit(n) 23816Salm int n; 23916Salm{ 24016Salm if (sfp) { 24116Salm fclose(sfp); 24216Salm unlink(sfn); 24316Salm } 24416Salm exit(n); 24516Salm} 24687Salm 24787Salm 24887Salmunsigned char ctab[256]; /* character translation table */ 24987Salm 2501057Salm/* init_buffers: open scratch buffer; initialize line queue */ 25187Salmvoid 2521057Salminit_buffers() 25387Salm{ 25487Salm int i = 0; 25587Salm 2568855Srgrimes /* Read stdin one character at a time to avoid i/o contention 2571057Salm with shell escapes invoked by nonterminal input, e.g., 2581057Salm ed - <<EOF 2591057Salm !cat 2601057Salm hello, world 2611057Salm EOF */ 2621057Salm setbuffer(stdin, stdinbuf, 1); 2631057Salm if (open_sbuf() < 0) 26487Salm quit(2); 2651057Salm REQUE(&buffer_head, &buffer_head); 26687Salm for (i = 0; i < 256; i++) 26787Salm ctab[i] = i; 26887Salm} 26987Salm 27087Salm 2711057Salm/* translit_text: translate characters in a string */ 27287Salmchar * 2731057Salmtranslit_text(s, len, from, to) 27487Salm char *s; 27587Salm int len; 27687Salm int from; 27787Salm int to; 27887Salm{ 27987Salm static int i = 0; 28087Salm 28187Salm unsigned char *us; 28287Salm 28387Salm ctab[i] = i; /* restore table to initial state */ 28487Salm ctab[i = from] = to; 28587Salm for (us = (unsigned char *) s; len-- > 0; us++) 28687Salm *us = ctab[*us]; 28787Salm return s; 28887Salm} 289