[comp.os.minix] ed part 1 of 2

ast@cs.vu.nl (Andy Tanenbaum) (09/14/87)

: This is a shar archive.  Extract with sh, not csh.
: This archive ends with exit, so do not worry about trailing junk.
: --------------------------- cut here --------------------------
PATH=/bin:/usr/bin
echo Extracting \a\m\a\t\c\h\.\c
sed 's/^X//' > \a\m\a\t\c\h\.\c << '+ END-OF-FILE '\a\m\a\t\c\h\.\c
X#include <stdio.h>
X#include "tools.h"
X
X/*     Scans throught the pattern template looking for a match
X * with lin.  Each element of lin is compared with the template
X * until either a mis-match is found or the end of the template
X * is reached.  In the former case a 0 is returned; in the latter,
X * a pointer into lin (pointing to the character following the
X * matched pattern) is returned.
X *
X *	"lin"	is a pointer to the line being searched.
X *	"pat"	is a pointer to a template made by makepat().
X *	"boln"	is a pointer into "lin" which points at the
X *			character at the beginning of the line.
X */
Xchar	*
Xamatch(lin, pat, boln)
Xchar	*lin;
XTOKEN	*pat;
Xchar	*boln;
X{
X	register char	*bocl, *rval, *strstart;
X
X	if(pat == 0)
X		return 0;
X
X	strstart = lin;
X
X	while(pat)
X	{
X		if(pat->tok == CLOSURE && pat->next)
X		{
X				/* Process a closure:
X				 * first skip over the closure token to the
X				 * object to be repeated.  This object can be
X				 * a character class.
X				 */
X
X			pat = pat->next;
X
X				/* Now match as many occurrences of the
X				 * closure pattern as possible.
X				 */
X			bocl = lin;
X
X			while( *lin && omatch(&lin, pat))
X				;
X
X				/* 'Lin' now points to the character that made
X				 * made us fail.  Now go on to process the
X				 * rest of the string.  A problem here is
X				 * a character following the closure which
X				 * could have been in the closure.
X				 * For example, in the pattern "[a-z]*t" (which
X				 * matches any lower-case word ending in a t),
X				 * the final 't' will be sucked up in the while
X				 * loop.  So, if the match fails, we back up a
X				 * notch and try to match the rest of the
X				 * string again, repeating this process
X				 * recursively until we get back to the
X				 * beginning of the closure.  The recursion
X				 * goes, at most two levels deep.
X				 */
X
X			if(pat = pat->next)
X			{
X				while(bocl <= lin)
X				{
X					if(rval = amatch(lin, pat, boln))
X					{
X							/* success */
X						return(rval);
X					} else
X						--lin;
X				}
X				return (0);	/* match failed */
X			}
X		} else if (omatch(&lin, pat, boln))
X		{
X			pat = pat->next;
X		} else {
X			return (0);
X		}
X	}
X		/* Note that omatch() advances lin to point at the next
X		 * character to be matched.  Consequently, when we reach
X		 * the end of the template, lin will be pointing at the
X		 * character following the last character matched.  The
X		 * exceptions are templates containing only a BOLN or EOLN
X		 * token.  In these cases omatch doesn't advance.
X		 *
X		 * A philosophical point should be mentioned here.  Is $
X		 * a position or a character? (i.e. does $ mean the EOL
X		 * character itself or does it mean the character at the end
X		 * of the line.)  I decided here to make it mean the former,
X		 * in order to make the behavior of amatch() consistent.  If
X		 * you give amatch the pattern ^$ (match all lines consisting
X		 * only of an end of line) then, since something has to be
X		 * returned, a pointer to the end of line character itself is
X		 * returned.
X		 */
X
X	return ((char *)max(strstart , lin));
X}
+ END-OF-FILE amatch.c
chmod 'u=rw,g=r,o=r' \a\m\a\t\c\h\.\c
set `sum \a\m\a\t\c\h\.\c`
sum=$1
case $sum in
63558)	:;;
*)	echo 'Bad sum in '\a\m\a\t\c\h\.\c >&2
esac
echo Extracting \a\p\p\e\n\d\.\c
sed 's/^X//' > \a\p\p\e\n\d\.\c << '+ END-OF-FILE '\a\p\p\e\n\d\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xappend(line, glob)
Xint	line, glob;
X{
X	int	stat;
X	char	lin[MAXLINE];
X
X	if(glob)
X		return(ERR);
X	curln = line;
X	while(1)
X	{
X		if(nflg)
X			fprintf(stdout,"%6d. ",curln+1);
X
X		if(fgets(lin, MAXLINE, stdin) == NULL)
X			return( EOF );
X		if(lin[0] == '.' && lin[1] == '\n')
X			return(0);
X		stat = ins(lin);
X		if(stat < 0)
X			return( ERR );
X		
X	}
X}
+ END-OF-FILE append.c
chmod 'u=rw,g=r,o=r' \a\p\p\e\n\d\.\c
set `sum \a\p\p\e\n\d\.\c`
sum=$1
case $sum in
24487)	:;;
*)	echo 'Bad sum in '\a\p\p\e\n\d\.\c >&2
esac
echo Extracting \b\i\t\m\a\p\.\c
sed 's/^X//' > \b\i\t\m\a\p\.\c << '+ END-OF-FILE '\b\i\t\m\a\p\.\c
X/*
X *	BITMAP.C -	makebitmap, setbit, testbit
X *			bit-map manipulation routines.
X *
X *	Copyright (c) Allen I. Holub, all rights reserved.  This program may
X *		for copied for personal, non-profit use only.
X *
X */
X 
X#ifdef DEBUG
X#include <stdio.h>
X#endif
X 
X#include "tools.h"
X 
X
XBITMAP	*makebitmap( size )
Xunsigned size;
X{
X	/*	Make a bit map with "size" bits.  The first entry in
X	 *	the map is an "unsigned int" representing the maximum
X	 *	bit.  The map itself is concatenated to this integer.
X	 *	Return a pointer to a map on success, 0 if there's
X	 *	not enough memory.
X	 */
X
X	unsigned *map, numbytes;
X
X	numbytes = (size >> 3) + ((size & 0x07) ? 1 : 0 );
X
X#ifdef DEBUG
X	printf("Making a %d bit map (%d bytes required)\n", size, numbytes);
X#endif
X
X	if( map = (unsigned *) malloc( numbytes + sizeof(unsigned) ))
X		*map = size;
X
X	return ((BITMAP *)map);
X}
X
Xsetbit( c, map, val )
Xunsigned	c, val;
Xchar		*map;
X{
X	/*	Set bit c in the map to val.
X	 *	If c > map-size, 0 is returned, else 1 is returned.
X	 */
X
X	if( c >= *(unsigned *)map )	/* if c >= map size */
X		return 0;
X
X	map += sizeof(unsigned);	/* skip past size */
X	
X	if( val )
X		map[c >> 3] |= 1 << (c & 0x07);
X	else
X		map[c >> 3] &= ~(1 << (c & 0x07));
X
X	return( 1 );
X}
X
Xtestbit( c, map )
Xunsigned	c;
Xchar		*map;
X{
X	/*	Return 1 if the bit corresponding to c in map is set.
X	 *	0 if it is not.
X	 */
X
X	if( c >= *(unsigned *)map )
X		return 0;
X
X	map += sizeof(unsigned);
X	
X	return(map[ c >> 3 ] & (1 << (c & 0x07)));
X}
+ END-OF-FILE bitmap.c
chmod 'u=rw,g=r,o=r' \b\i\t\m\a\p\.\c
set `sum \b\i\t\m\a\p\.\c`
sum=$1
case $sum in
33873)	:;;
*)	echo 'Bad sum in '\b\i\t\m\a\p\.\c >&2
esac
echo Extracting \c\a\t\s\u\b\.\c
sed 's/^X//' > \c\a\t\s\u\b\.\c << '+ END-OF-FILE '\c\a\t\s\u\b\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xchar	*
Xcatsub(from, to, sub, new, newend)
Xchar	*from, *to, *sub, *new, *newend;
X{
X	char	*cp, *cp2;
X
X	for(cp = new; *sub != EOS && cp < newend;)
X	{
X		if(*sub == DITTO)
X			for(cp2 = from; cp2 < to;)
X			{
X				*cp++ = *cp2++;
X				if(cp >= newend)
X					break;
X			}
X		else
X			*cp++ = *sub;
X		sub++;
X	}
X
X	return(cp);
X}
+ END-OF-FILE catsub.c
chmod 'u=rw,g=r,o=r' \c\a\t\s\u\b\.\c
set `sum \c\a\t\s\u\b\.\c`
sum=$1
case $sum in
19491)	:;;
*)	echo 'Bad sum in '\c\a\t\s\u\b\.\c >&2
esac
echo Extracting \c\k\g\l\o\b\.\c
sed 's/^X//' > \c\k\g\l\o\b\.\c << '+ END-OF-FILE '\c\k\g\l\o\b\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xckglob()
X{
X	static TOKEN	*glbpat;
X	char	c, delim, *lin;
X	int	num, nmatch;
X	LINE	*ptr;
X
X	c = toupper(*inptr);
X	nmatch = 0;
X
X	if(c == 'G' || c == 'V')
X	{
X		delim = *++inptr;
X		if(delim <= ' ')
X			return(0);
X		if(inptr[0] != inptr[1])	/* if null string use last */
X		{
X			glbpat = optpat(glbpat);
X		}
X		if(*inptr == delim)
X			inptr++;
X		num = curln;
X		while(1)
X		{
X			if(num)		/* do not do zero */
X			{
X				ptr = getptr(num);
X				lin = gettxt(num);
X				if(matchs(lin, glbpat, 0))
X				{
X					ptr->l_stat = (c == 'G' ? LGLOB:LEXCL);
X					nmatch++;
X				}
X			}
X			if((num = nextln(num)) == curln)
X				break;
X		}
X	}
X	return(nmatch);
X}
+ END-OF-FILE ckglob.c
chmod 'u=rw,g=r,o=r' \c\k\g\l\o\b\.\c
set `sum \c\k\g\l\o\b\.\c`
sum=$1
case $sum in
46924)	:;;
*)	echo 'Bad sum in '\c\k\g\l\o\b\.\c >&2
esac
echo Extracting \d\e\f\l\t\.\c
sed 's/^X//' > \d\e\f\l\t\.\c << '+ END-OF-FILE '\d\e\f\l\t\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xdeflt(def1, def2)
Xint	def1, def2;
X{
X	if(nlines == 0)
X	{
X		line1 = def1;
X		line2 = def2;
X	}
X	if(line1 > line2 || line1 <= 0)
X		return (ERR);
X}
+ END-OF-FILE deflt.c
chmod 'u=rw,g=r,o=r' \d\e\f\l\t\.\c
set `sum \d\e\f\l\t\.\c`
sum=$1
case $sum in
21184)	:;;
*)	echo 'Bad sum in '\d\e\f\l\t\.\c >&2
esac
echo Extracting \d\e\l\.\c
sed 's/^X//' > \d\e\l\.\c << '+ END-OF-FILE '\d\e\l\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xdel(from, to)
Xint	from, to;
X{
X	LINE	*first, *last, *next, *tmp;
X
X	if(from < 1)
X		from = 1;
X	first = getptr(prevln(from));
X	last = getptr(nextln(to));
X	next = first->l_next;
X	while(next != last && next != &line0)
X	{
X		tmp = next->l_next;
X		free(next);
X		next = tmp;
X	}
X	relink(first, last, first, last);
X	lastln -= (to - from)+1;
X	curln = prevln(from);
X}
+ END-OF-FILE del.c
chmod 'u=rw,g=r,o=r' \d\e\l\.\c
set `sum \d\e\l\.\c`
sum=$1
case $sum in
52329)	:;;
*)	echo 'Bad sum in '\d\e\l\.\c >&2
esac
echo Extracting \d\o\c\m\d\.\c
sed 's/^X//' > \d\o\c\m\d\.\c << '+ END-OF-FILE '\d\o\c\m\d\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xchar	fname[MAXFNAME];
Xint	fchanged;
X
Xdocmd(glob)
Xint	glob;
X{
X	static char	rhs[MAXPAT];
X	static TOKEN	*subpat;
X	int	c, err, line3;
X	int	i, apflg, pflag, gflag;
X	int	nchng;
X	char	*fptr;
X
X	pflag = FALSE;
X	while(*inptr == SP && *inptr == HT)
X		inptr++;
X
X	c = *inptr++;
X
X	switch(c)
X	{
X	case NL:
X		if(nlines == 0)
X		{
X			line2 = nextln(curln);
X		}
X		curln = line2;
X		return (1);
X		break;
X
X	case '=':
X		printf("%6d=\n",line2);
X		break;
X
X	case 'A':	
X	case 'a':
X		if(*inptr != NL || nlines > 1)
X			return(ERR);
X
X		if(append(line1, glob) < 0)
X			return(ERR);;
X		fchanged = TRUE;
X		break;
X
X	case 'C':
X	case 'c':
X		if(*inptr != NL)
X			return(ERR);
X
X		if(deflt(curln, curln) < 0)
X			return(ERR);
X
X		if(del(line1, line2) < 0)
X			return(ERR);
X		if(append(curln, glob) < 0)
X			return(ERR);
X		fchanged = TRUE;
X		break;
X
X	case 'D':
X	case 'd':
X		if(*inptr != NL)
X			return(ERR);
X
X		if(deflt(curln, curln) < 0)
X			return(ERR);
X
X		if(del(line1, line2) < 0)
X			return(ERR);
X		if(nextln(curln) != 0)
X			curln = nextln(curln);
X		fchanged = TRUE;
X		break;
X
X	case 'E':
X	case 'e':
X		if(nlines > 0)
X			return(ERR);
X		if(fchanged && *inptr != '!')
X		{
X			printf("File not saved\n");
X			return(ERR);
X		}
X		if(*inptr == '!')
X			inptr++;
X
X		if(*inptr != ' ' && *inptr != HT && *inptr != NL)
X			return(ERR);
X
X		if((fptr = getfn()) == NULL)
X			return(ERR);
X
X		clrbuf();
X		if((err = doread(0, fptr)) < 0)
X			return(err);
X
X		strcpy(fname, fptr);
X		fchanged = FALSE;
X		break;
X
X	case 'I':
X	case 'i':
X		if(*inptr != NL || nlines > 1)
X			return(ERR);
X
X		if(append(prevln(line1), glob) < 0)
X			return(ERR);
X		fchanged = TRUE;
X		break;
X
X	case 'M':
X	case 'm':
X		if((line3 = getone()) < 0)
X			return(ERR);
X		if(deflt(curln,curln) < 0)
X			return(ERR);
X		if(move(line3) < 0)
X			return(ERR);
X		fchanged = TRUE;
X		break;
X
X	case 'P':
X	case 'p':
X		if(*inptr != NL)
X			return(ERR);
X		if(deflt(curln,curln) < 0)
X			return(ERR);
X		if(doprnt(line1,line2) < 0)
X			return(ERR);
X		break;
X
X	case 'Q':
X	case 'q':
X		if(fchanged && *inptr != '!')
X		{
X			printf("File not saved\n");
X			return(ERR);
X		}
X		if(*inptr == '!')
X			inptr++;
X		if(*inptr == NL && nlines == 0 && !glob)
X			return(EOF);
X		else
X			return(ERR);
X
X	case 'R':
X	case 'r':
X		if(nlines > 1)
X			return(ERR);
X
X		if(nlines = 0)
X			line2 = lastln;
X
X		if(*inptr != ' ' && *inptr != HT && *inptr != NL)
X			return(ERR);
X
X		if((fptr = getfn()) == NULL)
X			return(ERR);
X
X		if((err = doread(line2, fptr)) < 0)
X			return(err);
X		fchanged = TRUE;
X		break;
X
X	case 'S':
X	case 's':
X		if(toupper(*inptr) == 'E')
X			return(set());
X		while(*inptr == SP || *inptr == HT)
X			inptr++;
X		if((subpat = optpat(subpat)) == NULL)
X			return(ERR);
X		if((gflag = getrhs(rhs)) < 0)
X			return(ERR);
X		if(toupper(*inptr) == 'P')
X			pflag++;
X		if(deflt(curln, curln) < 0)
X			return(ERR);
X		if((nchng = subst(subpat, rhs, gflag, pflag)) < 0)
X			return(ERR);
X		if(nchng)
X			fchanged = TRUE;
X		return (1);
X
X	case 'W':
X	case 'w':
X		apflg = 0;
X		if(inptr[0] == '>' && inptr[1] == '>')
X		{
X			apflg++;
X			inptr++;
X			inptr++;
X		}
X
X		if(*inptr != ' ' && *inptr != HT && *inptr != NL)
X			return(ERR);
X
X		if((fptr = getfn()) == NULL)
X			return(ERR);
X
X		if(deflt(1, lastln) < 0)
X			return(ERR);
X		if(dowrite(line1, line2, fptr, apflg) < 0)
X			return(ERR);
X		fchanged = FALSE;
X		break;
X
X	case 'X':
X	case 'x':
X		if(*inptr == NL && nlines == 0 && !glob)
X		{
X			if((fptr = getfn()) == NULL)
X				return(ERR);
X			if(dowrite(1, lastln, fptr, 0) >= 0)
X				return(EOF);
X		}
X		return(ERR);
X
X	case 'Z':
X	case 'z':
X		if(deflt(curln,curln) < 0)
X			return(ERR);
X
X		switch(*inptr)
X		{
X		case '-':
X			if(doprnt(line1-21,line1) < 0)
X				return(ERR);
X			break;
X
X		case '.':
X			if(doprnt(line1-11,line1+10) < 0)
X				return(ERR);
X			break;
X
X		case '+':
X		case '\n':
X			if(doprnt(line1,line1+21) < 0)
X				return(ERR);
X			break;
X		}
X		break;
X
X	default:
X		return(ERR);
X	}
X	return (0);
X}
+ END-OF-FILE docmd.c
chmod 'u=rw,g=r,o=r' \d\o\c\m\d\.\c
set `sum \d\o\c\m\d\.\c`
sum=$1
case $sum in
51484)	:;;
*)	echo 'Bad sum in '\d\o\c\m\d\.\c >&2
esac
echo Extracting \d\o\d\a\s\h\.\c
sed 's/^X//' > \d\o\d\a\s\h\.\c << '+ END-OF-FILE '\d\o\d\a\s\h\.\c
X#include <stdio.h>
X#include "tools.h"
X
X/*	Expand the set pointed to by *src into dest.
X *	Stop at delim.  Return 0 on error or size of
X *	character class on success.  Update *src to
X *	point at delim.  A set can have one element
X *	{x} or several elements ( {abcdefghijklmnopqrstuvwxyz}
X *	and {a-z} are equivalent ).  Note that the dash
X *	notation is expanded as sequential numbers.
X *	This means (since we are using the ASCII character
X *	set) that a-Z will contain the entire alphabet
X *	plus the symbols: [\]^_`.  The maximum number of
X *	characters in a character class is defined by maxccl.
X */
Xchar *
Xdodash(delim, src, map)
X
Xint	delim;
Xchar	*src, *map;
X{
X
X	register int	first,	last;
X	char		*start;
X
X	start = src;
X
X	while( *src && *src != delim )
X	{
X		if( *src != '-')
X			setbit( esc( &src ), map, 1 );
X
X		else if( src == start || *(src + 1) == delim )
X			setbit( '-', map, 1 );
X		else {
X			src++;
X
X			if( *src < *(src - 2))
X			{
X				first = *src;
X				last = *(src - 2);
X			} else {
X				first = *(src - 2);
X				last = *src;
X			}
X
X			while( ++first <= last )
X				setbit( first, map, 1);
X
X		}
X		src++;
X	}
X	return( src );
X}
+ END-OF-FILE dodash.c
chmod 'u=rw,g=r,o=r' \d\o\d\a\s\h\.\c
set `sum \d\o\d\a\s\h\.\c`
sum=$1
case $sum in
17370)	:;;
*)	echo 'Bad sum in '\d\o\d\a\s\h\.\c >&2
esac
echo Extracting \d\o\g\l\o\b\.\c
sed 's/^X//' > \d\o\g\l\o\b\.\c << '+ END-OF-FILE '\d\o\g\l\o\b\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xdoglob()
X{
X	int	cursav, lin, stat, count;
X	char	*cmd;
X	LINE	*ptr;
X
X	lin = 1;
X	count = 0;
X
X	cmd = inptr;
X	while(1)
X	{
X		ptr = getptr(lin);
X		if(ptr->l_stat & (LGLOB|LEXCL))
X		{
X			ptr->l_stat &= ~(LGLOB|LEXCL);
X			cursav = curln = lin;
X			inptr = cmd;
X			if((stat = getlst()) < 0)
X				return(stat);
X			if((stat = docmd(1)) < 0)
X				return(stat);
X			count = 0;
X		} else {
X			count++;
X			lin = nextln(lin);
X		}
X		if(count > lastln)
X			return(0);
X	}
X}
+ END-OF-FILE doglob.c
chmod 'u=rw,g=r,o=r' \d\o\g\l\o\b\.\c
set `sum \d\o\g\l\o\b\.\c`
sum=$1
case $sum in
03480)	:;;
*)	echo 'Bad sum in '\d\o\g\l\o\b\.\c >&2
esac
echo Extracting \d\o\p\r\n\t\.\c
sed 's/^X//' > \d\o\p\r\n\t\.\c << '+ END-OF-FILE '\d\o\p\r\n\t\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xdoprnt(from, to)
Xint	from, to;
X{
X	int	i;
X
X	from = from < 1 ? 1 : from;
X	to = to > lastln ? lastln : to;
X		
X	if(to != 0)
X	{
X		for(i = from; i <= to; i++)
X			prntln(gettxt(i), lflg, (nflg ? i : 0));
X		curln = to;
X	}
X
X	return(0);
X}
X
Xprntln(str, vflg, lin)
Xchar	*str;
Xint	vflg, lin;
X{
X	if(lin)
X		fprintf(stdout,"%7d ",lin);
X	while(*str && *str != NL)
X	{
X		if(*str < ' ' || *str >= 0x7f)
X		{
X			switch(*str)
X			{
X			case '\t':
X				if(vflg)
X					putcntl(*str, stdout);
X				else
X					putc(*str, stdout);
X				break;
X
X			case DEL:
X				putc('^', stdout);
X				putc('?', stdout);
X				break;
X
X			default:
X				putcntl(*str, stdout);
X				break;
X			}
X		} else
X			putc(*str, stdout);
X		str++;
X	}
X	if(vflg)
X		putc('$',stdout);
X	putc('\n', stdout);
X}
X
Xputcntl(c, stream)
Xchar	c;
XFILE	*stream;
X{
X	putc('^', stream);
X	putc((c&31)|'@', stream);
X}
+ END-OF-FILE doprnt.c
chmod 'u=rw,g=r,o=r' \d\o\p\r\n\t\.\c
set `sum \d\o\p\r\n\t\.\c`
sum=$1
case $sum in
05813)	:;;
*)	echo 'Bad sum in '\d\o\p\r\n\t\.\c >&2
esac
echo Extracting \d\o\r\e\a\d\.\c
sed 's/^X//' > \d\o\r\e\a\d\.\c << '+ END-OF-FILE '\d\o\r\e\a\d\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xdoread(lin, fname)
Xint	lin;
Xchar	*fname;
X{
X	extern FILE	*fopen();
X	FILE	*fp;
X	int	err;
X	long	bytes;
X	int	lines;
X	static char	str[MAXLINE];
X
X	err = 0;
X	nonascii = nullchar = truncated = 0;
X
X	printf("\"%s\" ",fname);
X	if((fp = fopen(fname, "r")) == NULL)
X	{
X		printf("file open err\n");
X		return( ERR );
X	}
X	curln = lin;
X	for(lines = 0, bytes = 0;(err = egets(str,MAXLINE,fp)) > 0;)
X	{
X		bytes += strlen(str);
X		if(ins(str) < 0)
X		{
X			printf("file insert error\n");
X			err++;
X			break;
X		}
X		lines++;
X	}
X	fclose(fp);
X	if(err < 0)
X		return(err);
X	printf("%d lines %d bytes",lines,bytes);
X	if(nonascii)
X		printf(" [%d non-ascii]",nonascii);
X	if(nullchar)
X		printf(" [%d nul]",nullchar);
X	if(truncated)
X		printf(" [%d lines truncated]",truncated);
X	printf("\n");
X	return( err );
X}
+ END-OF-FILE doread.c
chmod 'u=rw,g=r,o=r' \d\o\r\e\a\d\.\c
set `sum \d\o\r\e\a\d\.\c`
sum=$1
case $sum in
07945)	:;;
*)	echo 'Bad sum in '\d\o\r\e\a\d\.\c >&2
esac
echo Extracting \d\o\w\r\i\t\e\.\c
sed 's/^X//' > \d\o\w\r\i\t\e\.\c << '+ END-OF-FILE '\d\o\w\r\i\t\e\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xdowrite(from, to, fname, apflg)
Xint	from, to;
Xchar	*fname;
Xint	apflg;
X{
X	extern FILE	*fopen();
X	FILE	*fp;
X	int	lin, err;
X	int	lines, bytes;
X	char	*str;
X
X	err = 0;
X
X	lines = bytes = 0;
X	printf("\"%s\" ",fname);
X	if((fp = fopen(fname,(apflg?"a":"w"))) == NULL)
X	{
X		printf("file open error\n");
X		return( ERR );
X	}
X	for(lin = from; lin <= to; lin++)
X	{
X		str = gettxt(lin);
X		lines++;
X		bytes += strlen(str);
X		if(fputs(str, fp) == EOF)
X		{
X			printf("file write error\n");
X			err++;
X			break;
X		}
X	}
X	printf("%d lines %d bytes\n",lines,bytes);
X	fclose(fp);
X	return( err );
X}
+ END-OF-FILE dowrite.c
chmod 'u=rw,g=r,o=r' \d\o\w\r\i\t\e\.\c
set `sum \d\o\w\r\i\t\e\.\c`
sum=$1
case $sum in
45900)	:;;
*)	echo 'Bad sum in '\d\o\w\r\i\t\e\.\c >&2
esac
echo Extracting \e\d\.\c
sed 's/^X//' > \e\d\.\c << '+ END-OF-FILE '\e\d\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X#include <setjmp.h>
Xjmp_buf	env;
X
XLINE	line0;
Xint	curln = 0;
Xint	lastln = 0;
Xchar	*inptr;
Xstatic char	inlin[MAXLINE];
Xint	nflg, lflg, pflg, pflag;
Xint	line1, line2, nlines;
Xextern char	fname[];
Xint	version = 1;
X
Xintr()
X{
X	printf("Interrupt:\n");
X	longjmp(env, 1);
X}
X
Xmain(argc,argv)
Xint	argc;
Xchar	**argv;
X{
X	int	stat, i, j, prmpt;
X
X	setbuf();
X	prmpt = isatty(0);		/* if interactive */
X	if(argc > 1)
X	{
X		for(i = 1; i < argc; i++)
X		{
X			if(doread(0,argv[i]))
X				curln = 1;
X			strcpy(fname, argv[i]);
X			break;
X		}
X	}
X	while(1)
X	{
X		setjmp(env);
X		signal(2, intr);
X
X		if(nflg)
X			fprintf(stdout,"%d: ",curln);
X		else if(prmpt)
X			fprintf(stdout,": ");
X
X		if (fgets(inlin, sizeof(inlin),stdin) == NULL)
X		{
X			break;
X		}
X		if(*inlin == '!')
X		{
X			for(inptr = inlin; *inptr != NL; inptr++)
X				;
X			*inptr = EOS;
X			system(inlin+1);
X			continue;
X		}
X		inptr = inlin;
X		if(getlst() >= 0)
X			if(ckglob())
X			{
X				if((stat = doglob()) >= 0)
X				{
X					curln = stat;
X					continue;
X				}
X			} else {
X				if((stat = docmd(0)) >= 0)
X				{
X					if(stat == 1)
X						doprnt(curln, curln);
X					continue;
X				}
X			}
X		if(stat == EOF)
X		{
X			exit(0);
X		}
X		if(stat == FATAL)
X		{
X			fputs("FATAL ERROR\n",stderr);
X			exit(1);
X		}
X		fputs("\007",stderr);
X	}
X}
+ END-OF-FILE ed.c
chmod 'u=rw,g=r,o=r' \e\d\.\c
set `sum \e\d\.\c`
sum=$1
case $sum in
52523)	:;;
*)	echo 'Bad sum in '\e\d\.\c >&2
esac
echo Extracting \e\d\.\h
sed 's/^X//' > \e\d\.\h << '+ END-OF-FILE '\e\d\.\h
X/* ed.h */
X#define FATAL	(ERR-1)
Xstruct	line {
X	int		l_stat;		/* empty, mark */
X	struct line	*l_prev;
X	struct line	*l_next;
X	char		l_buff[1];
X};
X
Xtypedef struct line	LINE;
X
X#define LINFREE	1	/* entry not in use */
X#define LGLOB	2       /* line marked global */
X#define LEXCL	4	/* line marked exclude */
X
X#define MAXLINE	256	/* max number of chars per line */
X#define MAXPAT	256	/* max number of chars per replacement pattern */
X#define MAXFNAME 256	/* max file name size */
X
Xextern LINE	line0;
Xextern int	curln, lastln, line1, line2, nlines;
Xextern int	nflg;		/* print line number flag */
Xextern int	lflg;		/* print line in verbose mode */
Xextern int	pflg;		/* print current line after each command */
Xextern char	*inptr;			/* tty input buffer */
Xextern char	linbuf[], *linptr;	/* current line */
Xextern int	truncflg;	/* truncate long line flag */
Xextern int	eightbit;	/* save eighth bit */
Xextern int	nonascii;	/* count of non-ascii chars read */
Xextern int	nullchar;	/* count of null chars read */
Xextern int	truncated;	/* count of lines truncated */
Xextern int	fchanged;	/* file changed */
X
X#define nextln(l)	((l)+1 > lastln ? 0 : (l)+1)
X#define prevln(l)	((l)-1 < 0 ? lastln : (l)-1)
X
Xextern char	*getfn();
Xextern LINE	*getptr();
Xextern char	*gettxt();
Xextern char	*maksub();
Xextern TOKEN	*optpat();
X
Xextern char	*catsub();
X
Xextern char	*strcpy();
Xextern int	*malloc();
X/*********************************************************************/
+ END-OF-FILE ed.h
chmod 'u=rw,g=r,o=r' \e\d\.\h
set `sum \e\d\.\h`
sum=$1
case $sum in
34840)	:;;
*)	echo 'Bad sum in '\e\d\.\h >&2
esac
echo Extracting \e\g\e\t\s\.\c
sed 's/^X//' > \e\g\e\t\s\.\c << '+ END-OF-FILE '\e\g\e\t\s\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xint	truncflg = 1;	/* truncate long line flag */
Xint	eightbit = 1;	/* save eight bit */
Xint	nonascii, nullchar, truncated;
Xegets(str,size,stream)
Xchar	*str;
Xint	size;
XFILE	*stream;
X{
X	int	c, count;
X	char	*cp;
X
X	for(count = 0, cp = str; size > count;)
X	{
X		c = getc(stream);
X		if(c == EOF)
X		{
X			*cp++ = '\n';
X			*cp = EOS;
X			if(count)
X			{
X				printf("[Incomplete last line]\n");
X			}
X			return(count);
X		}
X		if(c == NL)
X		{
X			*cp++ = c;
X			*cp = EOS;
X			return(++count);
X		}
X		if(c > 127)
X		{
X			if(!eightbit)		/* if not saving eighth bit */
X				c = c&127;	/* strip eigth bit */
X			nonascii++;		/* count it */
X		}
X		if(c)
X		{
X			*cp++ = c;	/* not null, keep it */
X			count++;
X		} else 
X			nullchar++;	/* count nulls */
X	}
X	str[count-1] = EOS;
X	if(c != NL)
X	{
X		printf("truncating line\n");
X		truncated++;
X		while((c = getc(stream)) != EOF)
X			if(c == NL)
X				break;
X	}
X	return(count);
X}
+ END-OF-FILE egets.c
chmod 'u=rw,g=r,o=r' \e\g\e\t\s\.\c
set `sum \e\g\e\t\s\.\c`
sum=$1
case $sum in
00743)	:;;
*)	echo 'Bad sum in '\e\g\e\t\s\.\c >&2
esac
echo Extracting \e\s\c\.\c
sed 's/^X//' > \e\s\c\.\c << '+ END-OF-FILE '\e\s\c\.\c
X#include <stdio.h>
X#include "tools.h"
X
X/* Map escape sequences into their equivalent symbols.  Returns the
X * correct ASCII character.  If no escape prefix is present then s
X * is untouched and *s is returned, otherwise **s is advanced to point
X * at the escaped character and the translated character is returned.
X */
Xesc(s)
Xchar	**s;
X{
X	register int	rval;
X
X	
X	if (**s != ESCAPE)
X	{
X		rval = **s;
X	} else {
X		(*s)++;
X
X		switch(toupper(**s))
X		{
X		case '\000':
X			rval = ESCAPE;	break;
X		case 'S':
X			rval = ' ';	break;
X		case 'N':
X			rval = '\n';	break;
X		case 'T':
X			rval = '\t';	break;
X		case 'B':
X			rval = '\b';	break;
X		case 'R':
X			rval = '\r';	break;
X		default:
X			rval = **s;	break;
X		}
X	}
X
X	return (rval);
X}
+ END-OF-FILE esc.c
chmod 'u=rw,g=r,o=r' \e\s\c\.\c
set `sum \e\s\c\.\c`
sum=$1
case $sum in
30870)	:;;
*)	echo 'Bad sum in '\e\s\c\.\c >&2
esac
echo Extracting \f\i\n\d\.\c
sed 's/^X//' > \f\i\n\d\.\c << '+ END-OF-FILE '\f\i\n\d\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xfind(pat, dir)
XTOKEN	*pat;
Xint	dir;
X{
X	int	num;
X	char	*lin;
X
X	for(num = curln;(num = (dir ? nextln(num) : prevln(num))) != curln;)
X	{
X		lin = gettxt(num);
X		if(matchs(lin, pat, 0))
X		{
X			return(num);
X		}
X	}
X	return ( ERR );
X}
+ END-OF-FILE find.c
chmod 'u=rw,g=r,o=r' \f\i\n\d\.\c
set `sum \f\i\n\d\.\c`
sum=$1
case $sum in
38841)	:;;
*)	echo 'Bad sum in '\f\i\n\d\.\c >&2
esac
echo Extracting \g\e\t\f\n\.\c
sed 's/^X//' > \g\e\t\f\n\.\c << '+ END-OF-FILE '\g\e\t\f\n\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xextern char	fname[MAXFNAME];
Xchar	*
Xgetfn()
X{
X	static char	file[256];
X	char	*cp;
X
X	if(*inptr == NL)
X	{
X		strcpy(file, fname);
X	} else {
X		while(*inptr == SP || *inptr == HT)
X			inptr++;
X
X		cp = file;
X		while(*inptr && *inptr != NL && *inptr != SP && *inptr != HT)
X		{
X			*cp++ = *inptr++;
X		}
X		*cp = '\0';
X
X		if(strlen(file) == 0)
X		{
X			printf("bad file name\n");
X			return( NULL );
X		}
X	}
X
X	if(strlen(file) == 0)
X	{
X		printf("no file name\n");
X		return(NULL);
X	}
X	return( file );
X}
+ END-OF-FILE getfn.c
chmod 'u=rw,g=r,o=r' \g\e\t\f\n\.\c
set `sum \g\e\t\f\n\.\c`
sum=$1
case $sum in
02358)	:;;
*)	echo 'Bad sum in '\g\e\t\f\n\.\c >&2
esac
echo Extracting \g\e\t\l\s\t\.\c
sed 's/^X//' > \g\e\t\l\s\t\.\c << '+ END-OF-FILE '\g\e\t\l\s\t\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xgetlst()
X{
X	int	num;
X
X	line2 = 0;
X	for(nlines = 0; (num = getone()) >= 0;)
X	{
X		line1 = line2;
X		line2 = num;
X		nlines++;
X		if(*inptr != ',' && *inptr != ';')
X			break;
X		if(*inptr == ';')
X			curln = num;
X		inptr++;
X	}
X	nlines = min(nlines, 2);
X	if(nlines == 0)
X		line2 = curln;
X	if(nlines <= 1)
X		line1 = line2;
X
X	if(num == ERR)
X		return(num);
X	else
X		return(nlines);
X}
+ END-OF-FILE getlst.c
chmod 'u=rw,g=r,o=r' \g\e\t\l\s\t\.\c
set `sum \g\e\t\l\s\t\.\c`
sum=$1
case $sum in
58013)	:;;
*)	echo 'Bad sum in '\g\e\t\l\s\t\.\c >&2
esac
echo Extracting \g\e\t\n\u\m\.\c
sed 's/^X//' > \g\e\t\n\u\m\.\c << '+ END-OF-FILE '\g\e\t\n\u\m\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
XTOKEN	*srchpat;
Xchar	lstsrch;
Xgetnum()
X{
X	int	num;
X	char	c;
X
X	while(*inptr == SP || *inptr == HT)
X		inptr++;
X
X	if(*inptr >= '0' && *inptr <= '9')	/* line number */
X	{
X		for(num = 0; *inptr >= '0' && *inptr <= '9';)
X		{
X			num = (num * 10) + *inptr - '0';
X			inptr++;
X		}
X		return ( num > lastln ? ERR : num );
X	}
X
X	switch(c = *inptr)
X	{
X	case '.':
X		inptr++;
X		return (curln);
X
X	case '$':
X		inptr++;
X		return (lastln);
X
X	case '/':
X	case '?':
X		lstsrch = c;
X		srchpat = optpat(srchpat);
X		if(*inptr == c)
X			*inptr++;
X		return(find(srchpat,c == '/'?1:0));
X
X	case '-':
X	case '+':
X		return(curln);
X
X	default:
X		return ( EOF );		/* unknown address */
X	}
X}
+ END-OF-FILE getnum.c
chmod 'u=rw,g=r,o=r' \g\e\t\n\u\m\.\c
set `sum \g\e\t\n\u\m\.\c`
sum=$1
case $sum in
25408)	:;;
*)	echo 'Bad sum in '\g\e\t\n\u\m\.\c >&2
esac
echo Extracting \g\e\t\o\n\e\.\c
sed 's/^X//' > \g\e\t\o\n\e\.\c << '+ END-OF-FILE '\g\e\t\o\n\e\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xgetone()
X{
X	int	c, i, num;
X
X	if((num = getnum()) >= 0)
X	{
X		while(1)
X		{
X			while(*inptr == SP || *inptr == HT)
X				inptr++;
X
X			if(*inptr != '+'&& *inptr != '-')
X				break;
X                        c = *inptr++;
X
X			if((i = getnum()) < 0)
X				return ( i );
X			if(c == '+')
X			{
X				num += i;
X			} else {
X				num -= i;
X			}
X		}
X	}
X	return ( num );
X}
+ END-OF-FILE getone.c
chmod 'u=rw,g=r,o=r' \g\e\t\o\n\e\.\c
set `sum \g\e\t\o\n\e\.\c`
sum=$1
case $sum in
15814)	:;;
*)	echo 'Bad sum in '\g\e\t\o\n\e\.\c >&2
esac
echo Extracting \g\e\t\p\a\t\.\c
sed 's/^X//' > \g\e\t\p\a\t\.\c << '+ END-OF-FILE '\g\e\t\p\a\t\.\c
X#include <stdio.h>
X#include "tools.h"
X
X/* Translate arg into a TOKEN string */
XTOKEN	*
Xgetpat (arg)
Xchar	*arg;
X{
X	
X	return (makepat(arg, '\000'));
X}
+ END-OF-FILE getpat.c
chmod 'u=rw,g=r,o=r' \g\e\t\p\a\t\.\c
set `sum \g\e\t\p\a\t\.\c`
sum=$1
case $sum in
08917)	:;;
*)	echo 'Bad sum in '\g\e\t\p\a\t\.\c >&2
esac
echo Extracting \g\e\t\p\t\r\.\c
sed 's/^X//' > \g\e\t\p\t\r\.\c << '+ END-OF-FILE '\g\e\t\p\t\r\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
XLINE	*
Xgetptr(num)
Xint	num;
X{
X	LINE	*ptr;
X	int	j;
X
X	ptr = &line0;
X	j = 0;
X	for(j = 0; j < num; j++)
X		ptr = ptr->l_next;
X	return(ptr);
X}
+ END-OF-FILE getptr.c
chmod 'u=rw,g=r,o=r' \g\e\t\p\t\r\.\c
set `sum \g\e\t\p\t\r\.\c`
sum=$1
case $sum in
13048)	:;;
*)	echo 'Bad sum in '\g\e\t\p\t\r\.\c >&2
esac
echo Extracting \g\e\t\r\h\s\.\c
sed 's/^X//' > \g\e\t\r\h\s\.\c << '+ END-OF-FILE '\g\e\t\r\h\s\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xgetrhs(sub)
Xchar	*sub;
X{
X	if(inptr[0] == NL || inptr[1] == NL)	/* check for eol */
X		return( ERR );
X
X	if(maksub(sub, MAXPAT) == NULL)
X		return( ERR );
X	
X	inptr++;		/* skip over delimter */
X	while(*inptr == SP || *inptr == HT)
X			inptr++;
X	if(toupper(*inptr) == 'G')
X	{
X		*inptr++;
X		return( 1 );
X	}
X	return( 0 );
X}
+ END-OF-FILE getrhs.c
chmod 'u=rw,g=r,o=r' \g\e\t\r\h\s\.\c
set `sum \g\e\t\r\h\s\.\c`
sum=$1
case $sum in
60050)	:;;
*)	echo 'Bad sum in '\g\e\t\r\h\s\.\c >&2
esac
echo Extracting \g\e\t\t\x\t\.\c
sed 's/^X//' > \g\e\t\t\x\t\.\c << '+ END-OF-FILE '\g\e\t\t\x\t\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xchar	*
Xgettxt(num)
Xint	num;
X{
X	LINE	*lin;
X	static char	txtbuf[MAXLINE];
X
X	lin = getptr(num);
X	strcpy(txtbuf,lin->l_buff);
X	strcat(txtbuf,"\n");
X	return(txtbuf);
X}
+ END-OF-FILE gettxt.c
chmod 'u=rw,g=r,o=r' \g\e\t\t\x\t\.\c
set `sum \g\e\t\t\x\t\.\c`
sum=$1
case $sum in
62154)	:;;
*)	echo 'Bad sum in '\g\e\t\t\x\t\.\c >&2
esac
echo Extracting \i\n\s\.\c
sed 's/^X//' > \i\n\s\.\c << '+ END-OF-FILE '\i\n\s\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X 
Xins(str)
Xchar	*str;
X{
X	char	buf[MAXLINE], *cp;
X	LINE	*new, *cur, *nxt;
X
X	cp = buf;
X	while(1)
X	{
X		if((*cp = *str++) == NL)
X			*cp = EOS;
X		if(*cp)
X		{
X			cp++;
X			continue;
X		}
X		if((new = (LINE *)malloc(sizeof(LINE)+strlen(buf))) == NULL)
X			return( ERR ); 	/* no memory */
X
X		strcpy(new->l_buff,buf);	/* build new line */
X		cur = getptr(curln);		/* get current line */
X		nxt = getptr(nextln(curln));	/* get next line */
X		relink(cur, new, new, nxt);	/* add to linked list */
X		relink(new, nxt, cur, new);
X		lastln++;
X		curln++;
X
X		if(*str == EOS)		/* end of line ? */
X			return( 1 );
X
X		cp = buf;
X	}
X}
+ END-OF-FILE ins.c
chmod 'u=rw,g=r,o=r' \i\n\s\.\c
set `sum \i\n\s\.\c`
sum=$1
case $sum in
15263)	:;;
*)	echo 'Bad sum in '\i\n\s\.\c >&2
esac
echo Extracting \m\a\k\e\f\i\l\e
sed 's/^X//' > \m\a\k\e\f\i\l\e << '+ END-OF-FILE '\m\a\k\e\f\i\l\e
X.SUFFIXES:	.c .s
X
XCFLAGS = -F 
X
XOBJS =	append.s catsub.s ckglob.s deflt.s del.s docmd.s doglob.s\
X	doprnt.s doread.s dowrite.s ed.s egets.s find.s getfn.s getlst.s\
X	getnum.s getone.s getptr.s getrhs.s gettxt.s ins.s maksub.s move.s\
X	optpat.s set.s setbuf.s subst.s getpat.s matchs.s amatch.s\
X	unmkpat.s omatch.s makepat.s bitmap.s dodash.s esc.s system.s
X
Xed:	$(OBJS)
X	cc -i -o ed $(OBJS)
X
+ END-OF-FILE makefile
chmod 'u=rw,g=r,o=r' \m\a\k\e\f\i\l\e
set `sum \m\a\k\e\f\i\l\e`
sum=$1
case $sum in
35727)	:;;
*)	echo 'Bad sum in '\m\a\k\e\f\i\l\e >&2
esac
echo Extracting \m\a\k\e\p\a\t\.\c
sed 's/^X//' > \m\a\k\e\p\a\t\.\c << '+ END-OF-FILE '\m\a\k\e\p\a\t\.\c
X#include <stdio.h>
X#include "tools.h"
X
X/*
X * Make a pattern template from the strinng pointed to by arg.  Stop
X * when delim or '\000' or '\n' is found in arg.  Return a pointer to
X * the pattern template.
X *
X * The pattern template used here are somewhat different than those
X * used in the "Software Tools" book; each token is a structure of
X * the form TOKEN (see tools.h).  A token consists of an identifier,
X * a pointer to a string, a literal character and a pointer to another
X * token.  This last is 0 if there is no subsequent token.
X *
X * The one strangeness here is caused (again) by CLOSURE which has
X * to be put in front of the previous token.  To make this insertion a
X * little easier, the 'next' field of the last to point at the chain
X * (the one pointed to by 'tail) is made to point at the previous node.
X * When we are finished, tail->next is set to 0.
X */
XTOKEN *
Xmakepat(arg, delim)
Xchar	*arg;
Xint	delim;
X{
X	 TOKEN	*head, *tail, *ntok;
X	 char	buf[CLS_SIZE];
X	 int	error;
X
X	/*
X	 * Check for characters that aren't legal at the beginning of
X	 * a template.
X	 */
X
X	if (*arg=='\0' || *arg==delim || *arg=='\n' || *arg==CLOSURE)
X		return(0);
X
X	error = 0;
X	tail = head = NULL;
X
X	while (*arg && *arg != delim && *arg != '\n' && !error)
X	{
X		ntok = (TOKEN *)malloc(TOKSIZE);
X		ntok->lchar = '\000';
X		ntok->next = 0;
X
X		switch(*arg)
X		{
X		case ANY:
X			ntok->tok = ANY;
X			break;
X
X		case BOL:
X			if (head == 0)	/* then this is the first symbol */
X				ntok->tok = BOL;
X			else
X				ntok->tok = LITCHAR;
X				ntok->lchar = BOL;
X			break;
X
X		case EOL:
X			if(*(arg+1) == delim || *(arg+1) == '\000' ||
X					*(arg+1) == '\n')
X			{
X				ntok->tok = EOL;
X			} else {
X				ntok->tok = LITCHAR;
X				ntok->lchar = EOL;
X			}
X			break;
X
X		case CLOSURE:
X			if (head != 0)
X			{
X				switch (tail->tok)
X				{
X				case BOL:
X				case EOL:
X				case CLOSURE:
X					return (0);
X				
X				default:
X					ntok->tok = CLOSURE;
X				}
X			}
X			break;
X
X		case CCL:
X
X			if(*(arg + 1) == NEGATE)
X			{
X				ntok->tok = NCCL;
X				arg += 2;
X			} else {
X				ntok->tok = CCL;
X				arg++;
X			}
X
X			if( ntok->bitmap = makebitmap(CLS_SIZE) )
X				arg = dodash(CCLEND, arg, ntok->bitmap );
X			else {
X				fprintf(stderr,"Not enough memory for pat\n");
X				error = 1;
X			}
X			break;
X
X		default:
X			ntok->tok = LITCHAR;
X			ntok->lchar = esc(&arg);
X		}
X
X		if (error || ntok == 0)
X		{
X			unmakepat(head);
X			return (0);
X		} else if (head == 0)
X		{
X				/* This is the first node in the chain. */
X			
X			ntok->next = 0;
X			head = tail = ntok;
X		} else if (ntok->tok != CLOSURE)
X		{
X			/* Insert at end of list (after tail) */
X
X			tail->next = ntok;
X			ntok->next = tail;
X			tail = ntok;
X		} else if (head != tail)
X		{
X			/*
X			 * More than one node in the chain.  Insert the
X			 * CLOSURE node immediately in front of tail.
X			 */
X			
X			(tail->next)->next = ntok;
X			ntok->next = tail;
X		} else {
X			/*
X			 * Only one node in the chain,  Insert the CLOSURE
X			 * node at the head of the linked list.
X			 */
X			
X			ntok->next = head;
X			tail->next = ntok;
X			head = ntok;
X		}
X		arg++;
X	}
X
X	tail->next = 0;
X	return (head);
X}
+ END-OF-FILE makepat.c
chmod 'u=rw,g=r,o=r' \m\a\k\e\p\a\t\.\c
set `sum \m\a\k\e\p\a\t\.\c`
sum=$1
case $sum in
60826)	:;;
*)	echo 'Bad sum in '\m\a\k\e\p\a\t\.\c >&2
esac
echo Extracting \m\a\k\s\u\b\.\c
sed 's/^X//' > \m\a\k\s\u\b\.\c << '+ END-OF-FILE '\m\a\k\s\u\b\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xchar	*
Xmaksub(sub, subsz)
Xchar	*sub;
Xint	subsz;
X{
X	int	size;
X	char	delim, *cp;
X
X	size = 0;
X	cp = sub;
X
X	delim = *inptr++;
X	for(size = 0; *inptr != delim && *inptr != NL && size < subsz; size++)
X	{
X		if(*inptr == '&')
X		{
X			*cp++ = DITTO;
X			inptr++;
X		} else {
X			if(*inptr == ESCAPE)
X			{
X				inptr++;
X				if(*inptr < '0' || *inptr > '7')
X					switch(toupper(*++inptr))
X					{
X					case NL:
X						*cp++ == ESCAPE;
X						break;
X					case 'S':
X						*cp++ = SP;
X						inptr++;
X						break;
X					case 'N':
X						*cp++ = NL;
X						inptr++;
X						break;
X					case 'T':
X						*cp++ = HT;
X						inptr++;
X						break;
X					case 'B':
X						*cp++ = BS;
X						inptr++;
X						break;
X					case 'R':
X						*cp++ = CR;
X						inptr++;
X						break;
X					default:
X						*cp++ = *inptr;
X						inptr++;
X						break;
X					}
X				else {
X					*cp = 0;
X					while(*inptr >= '0' && *inptr <= '7')
X					{
X						*cp = (*cp << 3)+(*inptr-'0');
X						inptr++;
X					}
X					cp++;
X				}
X			} else
X				*cp++ = *inptr++;
X		}
X	}
X	if(size >= subsz)
X		return( NULL );
X
X	*cp = EOS;
X	return( sub );
X}
+ END-OF-FILE maksub.c
chmod 'u=rw,g=r,o=r' \m\a\k\s\u\b\.\c
set `sum \m\a\k\s\u\b\.\c`
sum=$1
case $sum in
37872)	:;;
*)	echo 'Bad sum in '\m\a\k\s\u\b\.\c >&2
esac
echo Extracting \m\a\t\c\h\s\.\c
sed 's/^X//' > \m\a\t\c\h\s\.\c << '+ END-OF-FILE '\m\a\t\c\h\s\.\c
X#include <stdio.h>
X#include "tools.h"
X
X/*
X * Compares line and pattern.  Line is a character string while pat
X * is a pattern template made by getpat().
X * Returns:
X *	1. A zero if no match was found.
X *
X *	2. A pointer to the last character satisfing the match
X *	   if ret_endp is non-zero.
X *
X *	3. A pointer to the beginning of the matched string if
X *	   ret_endp is zero.
X *
X * e.g.:
X *
X *	matchs ("1234567890", getpat("4[0-9]*7), 0);
X * will return a pointer to the '4', while:
X *
X *	matchs ("1234567890", getpat("4[0-9]*7), 1);
X * will return a pointer to the '7'.
X */
Xchar	*
Xmatchs(line, pat, ret_endp)
Xchar	*line;
XTOKEN	*pat;
Xint	ret_endp;
X{
X
X	char	*rval, *bptr;
X
X	bptr = line;
X
X	while(*line)
X	{
X		if ((rval = amatch(line, pat, bptr)) == 0)
X		{
X			line++;
X		} else {
X			if(rval > bptr && rval > line)
X				rval--;	/* point to last char matched */
X			rval = ret_endp ? rval : line;
X			break;
X		}
X	}
X	return (rval);
X}
+ END-OF-FILE matchs.c
chmod 'u=rw,g=r,o=r' \m\a\t\c\h\s\.\c
set `sum \m\a\t\c\h\s\.\c`
sum=$1
case $sum in
03605)	:;;
*)	echo 'Bad sum in '\m\a\t\c\h\s\.\c >&2
esac
echo Extracting \m\o\v\e\.\c
sed 's/^X//' > \m\o\v\e\.\c << '+ END-OF-FILE '\m\o\v\e\.\c
X/*
X * Copyright 1987 Brian Beattie Rights Reserved.
X *
X * Permission to copy and/or distribute granted under the
X * following conditions:
X *
X * 1). No charge may be made other than resonable charges
X *	for reproduction.
X *
X * 2). This notice must remain intact.
X *
X * 3). No further restrictions may be added.
X *
X */
X#include <stdio.h>
X#include "tools.h"
X#include "ed.h"
X
Xmove(num)
Xint	num;
X{
X	LINE	*k0, *k1, *k2, *k3;
X
X	if(line1 <= 0 || line1 <= num && num <= line2)
X		return( ERR );
X	k0 = getptr(prevln(line1));
X	k1 = getptr(line1);
X	k2 = getptr(line2);
X	k3 = getptr(nextln(line2));
X
X	relink(k0, k3, k0, k3);
X
X	if(num > line1)
X	{
X		curln = num;
X		num += line2-line1+1;
X	} else
X		curln = num + (line2 - line1 + 1);
X
X	k0 = getptr(num);
X	k3 = getptr(nextln(num));
X
X	relink(k0, k1, k2, k3);
X	relink(k2, k3, k0, k1);
X
X	return( 1 );
X}
+ END-OF-FILE move.c
chmod 'u=rw,g=r,o=r' \m\o\v\e\.\c
set `sum \m\o\v\e\.\c`
sum=$1
case $sum in
07064)	:;;
*)	echo 'Bad sum in '\m\o\v\e\.\c >&2
esac
exit 0