buf.c revision 30247
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 */ 2827963Ssteve 2916Salm#ifndef lint 3027963Ssteve#if 0 3120420Sstevestatic char * const rcsid = "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp"; 3227963Ssteve#else 3327963Sstevestatic char * const rcsid = 3430247Seivind "$Id: buf.c,v 1.13 1997/10/08 13:46:39 eivind Exp $"; 3527963Ssteve#endif 3616Salm#endif /* not lint */ 3716Salm 3816Salm#include <sys/file.h> 391297Salm#include <sys/stat.h> 4016Salm 4116Salm#include "ed.h" 4216Salm 4316Salm 4416SalmFILE *sfp; /* scratch file pointer */ 4516Salmoff_t sfseek; /* scratch file position */ 4616Salmint seek_write; /* seek before writing */ 471057Salmline_t buffer_head; /* incore buffer */ 4816Salm 491057Salm/* get_sbuf_line: get a line of text from the scratch file; return pointer 5016Salm to the text */ 5116Salmchar * 521057Salmget_sbuf_line(lp) 5316Salm line_t *lp; 5416Salm{ 551057Salm static char *sfbuf = NULL; /* buffer */ 561057Salm static int sfbufsz = 0; /* buffer size */ 571057Salm 5816Salm int len, ct; 5916Salm 601057Salm if (lp == &buffer_head) 6116Salm return NULL; 6216Salm seek_write = 1; /* force seek on write */ 6316Salm /* out of position */ 6416Salm if (sfseek != lp->seek) { 6516Salm sfseek = lp->seek; 6616Salm if (fseek(sfp, sfseek, SEEK_SET) < 0) { 6716Salm fprintf(stderr, "%s\n", strerror(errno)); 6816Salm sprintf(errmsg, "cannot seek temp file"); 6916Salm return NULL; 7016Salm } 7116Salm } 721057Salm len = lp->len; 731057Salm REALLOC(sfbuf, sfbufsz, len + 1, NULL); 7416Salm if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) { 7516Salm fprintf(stderr, "%s\n", strerror(errno)); 7616Salm sprintf(errmsg, "cannot read temp file"); 7716Salm return NULL; 7816Salm } 7916Salm sfseek += len; /* update file position */ 8016Salm sfbuf[len] = '\0'; 8116Salm return sfbuf; 8216Salm} 8316Salm 8416Salm 851057Salm/* put_sbuf_line: write a line of text to the scratch file and add a line node 8616Salm to the editor buffer; return a pointer to the end of the text */ 8716Salmchar * 881057Salmput_sbuf_line(cs) 8916Salm char *cs; 9016Salm{ 9116Salm line_t *lp; 9216Salm int len, ct; 9316Salm char *s; 9416Salm 9516Salm if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) { 9616Salm fprintf(stderr, "%s\n", strerror(errno)); 9716Salm sprintf(errmsg, "out of memory"); 9816Salm return NULL; 9916Salm } 10016Salm /* assert: cs is '\n' terminated */ 10116Salm for (s = cs; *s != '\n'; s++) 10216Salm ; 10316Salm if (s - cs >= LINECHARS) { 10416Salm sprintf(errmsg, "line too long"); 10516Salm return NULL; 10616Salm } 1071057Salm len = s - cs; 10816Salm /* out of position */ 10916Salm if (seek_write) { 11016Salm if (fseek(sfp, 0L, SEEK_END) < 0) { 11116Salm fprintf(stderr, "%s\n", strerror(errno)); 11216Salm sprintf(errmsg, "cannot seek temp file"); 11316Salm return NULL; 11416Salm } 11516Salm sfseek = ftell(sfp); 11616Salm seek_write = 0; 11716Salm } 1181057Salm /* assert: SPL1() */ 11916Salm if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) { 12016Salm sfseek = -1; 12116Salm fprintf(stderr, "%s\n", strerror(errno)); 12216Salm sprintf(errmsg, "cannot write temp file"); 12316Salm return NULL; 12416Salm } 12516Salm lp->len = len; 12616Salm lp->seek = sfseek; 1271057Salm add_line_node(lp); 12816Salm sfseek += len; /* update file position */ 12916Salm return ++s; 13016Salm} 13116Salm 13216Salm 1331057Salm/* add_line_node: add a line node in the editor buffer after the current line */ 13416Salmvoid 1351057Salmadd_line_node(lp) 13616Salm line_t *lp; 13716Salm{ 13816Salm line_t *cp; 13916Salm 1401057Salm cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */ 1411297Salm INSQUE(lp, cp); 1421057Salm addr_last++; 1431057Salm current_addr++; 14416Salm} 14516Salm 14616Salm 1471057Salm/* get_line_node_addr: return line number of pointer */ 14816Salmlong 1491057Salmget_line_node_addr(lp) 15016Salm line_t *lp; 15116Salm{ 1521057Salm line_t *cp = &buffer_head; 15316Salm long n = 0; 15416Salm 1551057Salm while (cp != lp && (cp = cp->q_forw) != &buffer_head) 15616Salm n++; 1571057Salm if (n && cp == &buffer_head) { 15849Salm sprintf(errmsg, "invalid address"); 15949Salm return ERR; 16049Salm } 16149Salm return n; 16216Salm} 16316Salm 16416Salm 1651057Salm/* get_addressed_line_node: return pointer to a line node in the editor buffer */ 16616Salmline_t * 1671057Salmget_addressed_line_node(n) 16816Salm long n; 16916Salm{ 1701057Salm static line_t *lp = &buffer_head; 17116Salm static long on = 0; 17216Salm 1731057Salm SPL1(); 17416Salm if (n > on) 1751057Salm if (n <= (on + addr_last) >> 1) 17616Salm for (; on < n; on++) 1771057Salm lp = lp->q_forw; 17816Salm else { 1791057Salm lp = buffer_head.q_back; 1801057Salm for (on = addr_last; on > n; on--) 1811057Salm lp = lp->q_back; 18216Salm } 18316Salm else 18416Salm if (n >= on >> 1) 18516Salm for (; on > n; on--) 1861057Salm lp = lp->q_back; 18716Salm else { 1881057Salm lp = &buffer_head; 18916Salm for (on = 0; on < n; on++) 1901057Salm lp = lp->q_forw; 19116Salm } 1921057Salm SPL0(); 19316Salm return lp; 19416Salm} 19516Salm 19616Salm 1971057Salmextern int newline_added; 1981057Salm 19916Salmchar sfn[15] = ""; /* scratch file name */ 20016Salm 2011057Salm/* open_sbuf: open scratch file */ 2021057Salmint 2031057Salmopen_sbuf() 20416Salm{ 20524181Simp int fd = -1; 2061297Salm int u; 2071297Salm 2081057Salm isbinary = newline_added = 0; 2091297Salm u = umask(077); 21016Salm strcpy(sfn, "/tmp/ed.XXXXXX"); 21130247Seivind if ((fd = mkstemp(sfn)) == -1 || 21224181Simp (sfp = fdopen(fd, "w+")) == NULL) { 21324181Simp if (fd != -1) 21424181Simp close(fd); 21524181Simp perror(sfn); 21624181Simp strcpy(errmsg, "cannot open temp file"); 2171297Salm umask(u); 21816Salm return ERR; 21916Salm } 2201297Salm umask(u); 22116Salm return 0; 22216Salm} 22316Salm 22416Salm 2251057Salm/* close_sbuf: close scratch file */ 2261057Salmint 2271057Salmclose_sbuf() 22816Salm{ 22916Salm if (sfp) { 23016Salm if (fclose(sfp) < 0) { 23116Salm fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); 23216Salm sprintf(errmsg, "cannot close temp file"); 23316Salm return ERR; 23416Salm } 23516Salm sfp = NULL; 23616Salm unlink(sfn); 23716Salm } 23816Salm sfseek = seek_write = 0; 23916Salm return 0; 24016Salm} 24116Salm 24216Salm 2431057Salm/* quit: remove_lines scratch file and exit */ 24416Salmvoid 24516Salmquit(n) 24616Salm int n; 24716Salm{ 24816Salm if (sfp) { 24916Salm fclose(sfp); 25016Salm unlink(sfn); 25116Salm } 25216Salm exit(n); 25316Salm} 25487Salm 25587Salm 25687Salmunsigned char ctab[256]; /* character translation table */ 25787Salm 2581057Salm/* init_buffers: open scratch buffer; initialize line queue */ 25987Salmvoid 2601057Salminit_buffers() 26187Salm{ 26287Salm int i = 0; 26387Salm 2648855Srgrimes /* Read stdin one character at a time to avoid i/o contention 2651057Salm with shell escapes invoked by nonterminal input, e.g., 2661057Salm ed - <<EOF 2671057Salm !cat 2681057Salm hello, world 2691057Salm EOF */ 2701057Salm setbuffer(stdin, stdinbuf, 1); 2711057Salm if (open_sbuf() < 0) 27287Salm quit(2); 2731057Salm REQUE(&buffer_head, &buffer_head); 27487Salm for (i = 0; i < 256; i++) 27587Salm ctab[i] = i; 27687Salm} 27787Salm 27887Salm 2791057Salm/* translit_text: translate characters in a string */ 28087Salmchar * 2811057Salmtranslit_text(s, len, from, to) 28287Salm char *s; 28387Salm int len; 28487Salm int from; 28587Salm int to; 28687Salm{ 28787Salm static int i = 0; 28887Salm 28987Salm unsigned char *us; 29087Salm 29187Salm ctab[i] = i; /* restore table to initial state */ 29287Salm ctab[i = from] = to; 29387Salm for (us = (unsigned char *) s; len-- > 0; us++) 29487Salm *us = ctab[*us]; 29587Salm return s; 29687Salm} 297