io.c

     1	/* io.c: This file contains the i/o routines for the ed line editor */
     2	/*-
     3	 * Copyright (c) 1993 Andrew Moore, Talke Studio.
     4	 * All rights reserved.
     5	 *
     6	 * Redistribution and use in source and binary forms, with or without
     7	 * modification, are permitted provided that the following conditions
     8	 * are met:
     9	 * 1. Redistributions of source code must retain the above copyright
    10	 *    notice, this list of conditions and the following disclaimer.
    11	 * 2. Redistributions in binary form must reproduce the above copyright
    12	 *    notice, this list of conditions and the following disclaimer in the
    13	 *    documentation and/or other materials provided with the distribution.
    14	 *
    15	 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    16	 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    17	 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    18	 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    19	 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    20	 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    21	 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    22	 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    23	 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    24	 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    25	 * SUCH DAMAGE.
    26	 */
    27
    28	#include <sys/cdefs.h>
    29	__FBSDID("$FreeBSD: src/bin/ed/io.c,v 1.14 2003/01/01 18:48:39 schweikh Exp $");
    30
    31	#include "ed.h"
    32
    33
    34	extern int scripted;
    35
    36	/* read_file: read a named file/pipe into the buffer; return line count */
    37	long
    38	read_file(char *fn, long n)
    39	{
    40		FILE *fp;
    41		long size;
    42
    43
    44		fp = (*fn == '!') ? popen(fn + 1, "r") : fopen(strip_escapes(fn), "r");
    45		if (fp == NULL) {
    46			fprintf(stderr, "%s: %s\n", fn, strerror(errno));
    47			errmsg = "cannot open input file";
    48			return ERR;
    49		} else if ((size = read_stream(fp, n)) < 0)
    50			return ERR;
    51		 else if (((*fn == '!') ?  pclose(fp) : fclose(fp)) < 0) {
    52			fprintf(stderr, "%s: %s\n", fn, strerror(errno));
    53			errmsg = "cannot close input file";
    54			return ERR;
    55		}
    56		fprintf(stdout, !scripted ? "%lu\n" : "", size);
    57		return current_addr - n;
    58	}
    59
    60
    61	extern int des;
    62
    63	char *sbuf;			/* file i/o buffer */
    64	int sbufsz;			/* file i/o buffer size */
    65	int newline_added;		/* if set, newline appended to input file */
    66
    67	/* read_stream: read a stream into the editor buffer; return status */
    68	long
    69	read_stream(FILE *fp, long n)
    70	{
    71		line_t *lp = get_addressed_line_node(n);
    72		undo_t *up = NULL;
    73		unsigned long size = 0;
    74		int o_newline_added = newline_added;
    75		int o_isbinary = isbinary;
    76		int appended = (n == addr_last);
    77		int len;
    78
    79		isbinary = newline_added = 0;
    80		if (des)
    81			init_des_cipher();
    82		for (current_addr = n; (len = get_stream_line(fp)) > 0; size += len) {
    83			SPL1();
    84			if (put_sbuf_line(sbuf) == NULL) {
    85				SPL0();
    86				return ERR;
    87			}
    88			lp = lp->q_forw;
    89			if (up)
    90				up->t = lp;
    91			else if ((up = push_undo_stack(UADD, current_addr,
    92			    current_addr)) == NULL) {
    93				SPL0();
    94				return ERR;
    95			}
    96			SPL0();
    97		}
    98		if (len < 0)
    99			return ERR;
   100		if (appended && size && o_isbinary && o_newline_added)
   101			fputs("newline inserted\n", stderr);
   102		else if (newline_added && (!appended || (!isbinary && !o_isbinary)))
   103			fputs("newline appended\n", stderr);
   104		if (isbinary && newline_added && !appended)
   105		    	size += 1;
   106		if (!size)
   107			newline_added = 1;
   108		newline_added = appended ? newline_added : o_newline_added;
   109		isbinary = isbinary | o_isbinary;
   110		if (des)
   111			size += 8 - size % 8;			/* adjust DES size */
   112		return size;
   113	}
   114
   115
   116	/* get_stream_line: read a line of text from a stream; return line length */
   117	int
   118	get_stream_line(FILE *fp)
   119	{
   120		int c;
   121		int i = 0;
   122
   123		while (((c = des ? get_des_char(fp) : getc(fp)) != EOF || (!feof(fp) &&
   124		    !ferror(fp))) && c != '\n') {
   125			REALLOC(sbuf, sbufsz, i + 1, ERR);
   126			if (!(sbuf[i++] = c))
   127				isbinary = 1;
   128		}
   129		REALLOC(sbuf, sbufsz, i + 2, ERR);
   130		if (c == '\n')
   131			sbuf[i++] = c;
   132		else if (ferror(fp)) {
   133			fprintf(stderr, "%s\n", strerror(errno));
   134			errmsg = "cannot read input file";
   135			return ERR;
   136		} else if (i) {
   137			sbuf[i++] = '\n';
   138			newline_added = 1;
   139		}
   140		sbuf[i] = '\0';
   141		return (isbinary && newline_added && i) ? --i : i;
   142	}
   143
   144
   145	/* write_file: write a range of lines to a named file/pipe; return line count */
   146	long
   147	write_file(char *fn, const char *mode, long n, long m)
   148	{
   149		FILE *fp;
   150		long size;
   151
   152		fp = (*fn == '!') ? popen(fn+1, "w") : fopen(strip_escapes(fn), mode);
   153		if (fp == NULL) {
   154			fprintf(stderr, "%s: %s\n", fn, strerror(errno));
   155			errmsg = "cannot open output file";
   156			return ERR;
   157		} else if ((size = write_stream(fp, n, m)) < 0)
   158			return ERR;
   159		 else if (((*fn == '!') ?  pclose(fp) : fclose(fp)) < 0) {
   160			fprintf(stderr, "%s: %s\n", fn, strerror(errno));
   161			errmsg = "cannot close output file";
   162			return ERR;
   163		}
   164		fprintf(stdout, !scripted ? "%lu\n" : "", size);
   165		return n ? m - n + 1 : 0;
   166	}
   167
   168
   169	/* write_stream: write a range of lines to a stream; return status */
   170	long
   171	write_stream(FILE *fp, long n, long m)
   172	{
   173		line_t *lp = get_addressed_line_node(n);
   174		unsigned long size = 0;
   175		char *s;
   176		int len;
   177
   178		if (des)
   179			init_des_cipher();
   180		for (; n && n <= m; n++, lp = lp->q_forw) {
   181			if ((s = get_sbuf_line(lp)) == NULL)
   182				return ERR;
   183			len = lp->len;
   184			if (n != addr_last || !isbinary || !newline_added)
   185				s[len++] = '\n';
   186			if (put_stream_line(fp, s, len) < 0)
   187				return ERR;
   188			size += len;
   189		}
   190		if (des) {
   191			flush_des_file(fp);			/* flush buffer */
   192			size += 8 - size % 8;			/* adjust DES size */
   193		}
   194		return size;
   195	}
   196
   197
   198	/* put_stream_line: write a line of text to a stream; return status */
   199	int
   200	put_stream_line(FILE *fp, const char *s, int len)
   201	{
   202		while (len--)
   203			if ((des ? put_des_char(*s++, fp) : fputc(*s++, fp)) < 0) {
   204				fprintf(stderr, "%s\n", strerror(errno));
   205				errmsg = "cannot write file";
   206				return ERR;
   207			}
   208		return 0;
   209	}
   210
   211	/* get_extended_line: get an extended line from stdin */
   212	char *
   213	get_extended_line(int *sizep, int nonl)
   214	{
   215		static char *cvbuf = NULL;		/* buffer */
   216		static int cvbufsz = 0;			/* buffer size */
   217
   218		int l, n;
   219		char *t = ibufp;
   220
   221		while (*t++ != '\n')
   222			;
   223		if ((l = t - ibufp) < 2 || !has_trailing_escape(ibufp, ibufp + l - 1)) {
   224			*sizep = l;
   225			return ibufp;
   226		}
   227		*sizep = -1;
   228		REALLOC(cvbuf, cvbufsz, l, NULL);
   229		memcpy(cvbuf, ibufp, l);
   230		*(cvbuf + --l - 1) = '\n'; 	/* strip trailing esc */
   231		if (nonl) l--; 			/* strip newline */
   232		for (;;) {
   233			if ((n = get_tty_line()) < 0)
   234				return NULL;
   235			else if (n == 0 || ibuf[n - 1] != '\n') {
   236				errmsg = "unexpected end-of-file";
   237				return NULL;
   238			}
   239			REALLOC(cvbuf, cvbufsz, l + n, NULL);
   240			memcpy(cvbuf + l, ibuf, n);
   241			l += n;
   242			if (n < 2 || !has_trailing_escape(cvbuf, cvbuf + l - 1))
   243				break;
   244			*(cvbuf + --l - 1) = '\n'; 	/* strip trailing esc */
   245			if (nonl) l--; 			/* strip newline */
   246		}
   247		REALLOC(cvbuf, cvbufsz, l + 1, NULL);
   248		cvbuf[l] = '\0';
   249		*sizep = l;
   250		return cvbuf;
   251	}
   252
   253
   254	/* get_tty_line: read a line of text from stdin; return line length */
   255	int
   256	get_tty_line(void)
   257	{
   258		int oi = 0;
   259		int i = 0;
   260		int c;
   261
   262		for (;;)
   263			switch (c = getchar()) {
   264			default:
   265				oi = 0;
   266				REALLOC(ibuf, ibufsz, i + 2, ERR);
   267				if (!(ibuf[i++] = c)) isbinary = 1;
   268				if (c != '\n')
   269					continue;
   270				lineno++;
   271				ibuf[i] = '\0';
   272				ibufp = ibuf;
   273				return i;
   274			case EOF:
   275				if (ferror(stdin)) {
   276					fprintf(stderr, "stdin: %s\n", strerror(errno));
   277					errmsg = "cannot read stdin";
   278					clearerr(stdin);
   279					ibufp = NULL;
   280					return ERR;
   281				} else {
   282					clearerr(stdin);
   283					if (i != oi) {
   284						oi = i;
   285						continue;
   286					} else if (i)
   287						ibuf[i] = '\0';
   288					ibufp = ibuf;
   289					return i;
   290				}
   291			}
   292	}
   293
   294
   295
   296	#define ESCAPES "\a\b\f\n\r\t\v\\"
   297	#define ESCCHARS "abfnrtv\\"
   298
   299	extern int rows;
   300	extern int cols;
   301
   302	/* put_tty_line: print text to stdout */
   303	int
   304	put_tty_line(const char *s, int l, long n, int gflag)
   305	{
   306		int col = 0;
   307		char *cp;
   308
   309		if ((gflag & GNP) && !(gflag & GINT)) {
   310			printf("%ld\t", n);
   311			col = 8;
   312		}
   313		for (; l--; s++) {
   314			if ((gflag & GLS) && ++col > cols) {
   315				fputs("\\\n", stdout);
   316				col = 1;
   317			}
   318			if (gflag & GLS) {
   319				if (31 < *s && *s < 127 && *s != '\\')
   320					putchar(*s);
   321				else {
   322					putchar('\\');
   323					col++;
   324					if (*s && (cp = strchr(ESCAPES, *s)) != NULL)
   325						putchar(ESCCHARS[cp - ESCAPES]);
   326					else {
   327						putchar((((unsigned char) *s & 0300) >> 6) + '0');
   328						putchar((((unsigned char) *s & 070) >> 3) + '0');
   329						putchar(((unsigned char) *s & 07) + '0');
   330						col += 2;
   331					}
   332				}
   333
   334			} else
   335				putchar(*s);
   336		}
   337		if (posixly_correct && (gflag & GLS) && !(gflag & GINT))
   338			putchar('$');
   339		putchar('\n');
   340		return 0;
   341	}

Generated by GNU Enscript 1.6.6.