[mod.sources] v09i029: A TECO text editor, Part02/04

sources-request@mirror.UUCP (03/13/87)

Submitted by: genrad!mlf
Mod.sources: Volume 9, Issue 29
Archive-name: teco/Part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
#		"End of archive 2 (of 4)."
# Contents:  te_chario.c te_defs.h te_srch.c te_subs.c
# Wrapped by rs@mirror on Thu Mar 12 19:54:28 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"te_chario.c\" \(9049 characters\)
if test -f te_chario.c ; then 
  echo shar: Will not over-write existing file \"te_chario.c\"
else
sed "s/^X//" >te_chario.c <<'END_OF_te_chario.c'
X/* TECO for Ultrix   Copyright 1986 Matt Fichtenbaum						*/
X/* This program and its components belong to GenRad Inc, Concord MA 01742	*/
X/* They may be copied if this copyright notice is included					*/
X
X/* te_chario.c   character I/O routines   10/9/86 */
X#include <errno.h>
X#include "te_defs.h"
X
X#include <fcntl.h>
X#ifndef DEBUG
X#include <signal.h>
Xextern int int_handler();
Xextern int stp_handler();
Xextern int hup_handler();
X#define SIGINTMASK 2
X#endif
X
Xint lf_sw;									/* nonzero: make up a LF following an entered CR */
Xint ttyflags;								/* flags for (stdin) file descriptor */
Xstruct tchars tc_orig, tc_new, tc_noint;	/* original, new, disabled intrpt tty special chars */
Xstruct ltchars lc_orig, lc_new;				/* original and new local special chars */
Xstruct sgttyb tty_orig, tty_new;			/* original and new tty flags */
Xint tty_local;								/* original tty local mode flags */
Xint lnoflsh = LNOFLSH;						/* bit to force "no flush on interrupt */
X
X#ifndef DEBUG
Xstruct sigvec intsigstruc = { int_handler, 0, 0 } ;		/* info structure for ^C interrupt		*/
Xstruct sigvec stpsigstruc = { stp_handler, 0, 0 } ;		/* info structure for "stop" signal		*/
Xstruct sigvec hupsigstruc = { hup_handler, 0, 0 } ;		/* info structure for "hangup" signal	*/
Xstruct sigvec nosigstr = { SIG_DFL, 0, 0 };				/* default structure for signal			*/
X#endif
X
Xint inp_noterm;				/* nonzero if standard input is not a terminal */
Xint out_noterm;				/* nonzero if standard output is not a terminal */
X/* set tty (stdin) mode.  TECO mode is CBREAK, no ECHO, sep CR & LF				*/
X/* operation; normal mode is none of the above.  TTY_OFF and TTY_ON do this		*/
X/* absolutely; TTY_SUSP and TTY_RESUME use saved signal status.					*/
X
Xsetup_tty(arg)
X	int arg;
X	{
X	extern int errno;
X	int ioerr;
X	struct sgttyb tmpbuf;
X
X/* initial processing: set tty mode */
X
X	if (arg == TTY_ON)
X		{
X		ioerr = ioctl(fileno(stdin), TIOCGETP, &tty_orig);	/* get std input characteristics */
X		inp_noterm = (ioerr && (errno == ENOTTY));			/* nonzero if input not a terminal */
X		ioerr = ioctl(fileno(stdout), TIOCGETP, &tmpbuf);	/* get std output characteristics */
X		out_noterm = (ioerr && (errno == ENOTTY));			/* nonzero if output not a terminal */
X		ioctl(fileno(stdout), TIOCLGET, &tty_local);		/* get current "local mode flags" word */
X
X		ttybuf = tty_new = tty_orig;						/* make a copy of tty control structure */
X		tty_new.sg_flags = (tty_new.sg_flags & ~ECHO & ~CRMOD) | CBREAK;	/* turn on teco modes */
X
X		ioctl(fileno(stdin), TIOCGETC, &tc_orig);		/* read current tchars */
X		tc_new = tc_orig;								/* make local copy */
X		tc_new.t_quitc = tc_new.t_brkc = -1;			/* disable "quit" and "delimiter" chars */
X		tc_noint = tc_new;
X		tc_noint.t_intrc = -1;							/* disable the interrupt char in this one */
X
X		ioctl(fileno(stdin), TIOCGLTC, &lc_orig);		/* read current ltchars */
X		lc_new = lc_orig;								/* make local copy */
X		lc_new.t_rprntc = lc_new.t_werasc = lc_new.t_lnextc = -1;	/* disable "reprint," "word erase," "lit next" */
X		}
X
X	if ((arg == TTY_ON) || (arg == TTY_RESUME))
X		{
X		ioctl(fileno(stdin), TIOCSETP, &tty_new);		/* set flags for teco */
X		ioctl(fileno(stdin), TIOCSETC, &tc_new);		/* update both */
X		ioctl(fileno(stdin), TIOCSLTC, &lc_new);
X		ioctl(fileno(stdout), TIOCLBIS, &lnoflsh);		/* disable "interrupt => flush buffers" */
X#ifndef DEBUG
X		sigvec(SIGTSTP, &stpsigstruc, 0);				/* set up to trap "stop" signal */
X		sigvec(SIGINT, &intsigstruc, 0);				/* and "interrupt" signal */
X		sigvec(SIGHUP, &hupsigstruc, 0);				/* and "hangup" signal */
X#endif
X		}
X	else
X		{
X		ioctl(fileno(stdin), TIOCSETP, &tty_orig);		/* set flags back to original */
X		ioctl(fileno(stdin), TIOCSETC, &tc_orig);		/* put both back to orig states */
X		ioctl(fileno(stdin), TIOCSLTC, &lc_orig);
X		ioctl(fileno(stdout), TIOCLSET, &tty_local);	/* restore local mode flags to original states */
X#ifndef DEBUG
X		sigvec(SIGTSTP, &nosigstr, 0);					/* restore default signal handling */
X		sigvec(SIGINT, &nosigstr, 0);
X		sigvec(SIGHUP, &nosigstr, 0);
X#endif
X		}
X	}
X/* routines to handle keyboard input */
X
X/* routine to get a character without waiting, used by ^T when ET & 64 is set	*/
X/* if lf_sw is nonzero, return the LF; else use the FNDELAY fcntl to inquire of the input */
X
Xint gettty_nowait()
X	{
X	int c;
X
X	if (lf_sw)
X		{
X		lf_sw = 0;
X		return(LF);			/* LF to be sent: return it */
X		}
X	fcntl(fileno(stdin), F_SETFL, ttyflags | FNDELAY);		/* set to "no delay" mode */
X	while (!(c = getchar()));					/* read character, or -1, skip nulls */
X	fcntl(fileno(stdin), F_SETFL, ttyflags);				/* reset to normal mode */
X	if (c == CR) ++lf_sw;						/* CR: set switch to make up a LF */
X	return(c);
X	}
X
X
X
X/* normal routine to get a character */
X
Xint in_read = 0;		/* flag for "read busy" (used by interrupt handler) */
X
Xchar gettty()
X	{
X	int c;
X
X	if (lf_sw)
X		{
X		lf_sw = 0;
X		return(LF);		/* if switch set, make up a line feed */
X		}
X	++in_read;							/* set "read busy" switch */
X	while(!(c = getchar()));				/* get character; skip nulls */
X	in_read = 0;						/* clear switch */
X	if (c == CR) ++lf_sw;					/* CR: set switch to make up a LF */
X	if (c == EOF) ERROR(E_EFI);				/* end-of-file from standard input */
X	return( (char) c & 0177);				/* and return the 7-bit char */
X	}
X
X#ifndef DEBUG
X
X/* routine to handle interrupt signal */
X
Xint_handler()
X	{
X
X	if (exitflag <= 0)						/* if executing commands */
X		{
X		if (et_val & ET_CTRLC) et_val &= ~ET_CTRLC;		/* if "trap ^C" set, clear it and ignore */
X		else exitflag = -2;								/* else set flag to stop execution */
X		}
X	if (in_read)							/* if interrupt happened in "getchar" pass a ^C to input */
X		{
X		in_read = 0;									/* clear "read" switch */
X		ioctl(fileno(stdin), TIOCSETC, &tc_noint);		/* disable interrupt char */
X		qio_char(CTL (C));								/* send a ^C to input stream */
X		ioctl(fileno(stdin), TIOCSETC, &tc_new);		/* reenable interrupt char */
X		}
X	}
X#endif
X/* routine to disable (1), enable (0) ^C interrupt, used to block interrupts during display update */
X
Xint old_mask;				/* storage for previous signal mask */
X#define INT_MASK 2
X
Xblock_inter(func)
X	int func;
X	{
X#ifndef DEBUG
X	if (func) old_mask = sigblock(INT_MASK);			/* if arg nonzero, block interrupt */
X	else sigsetmask(old_mask);							/* otherwise restore old signal mask */
X#endif
X	}
X
X
X
X#ifndef DEBUG
X/* routine to handle "stop" signal (^Y) */
X
Xstp_handler()
X	{
X	window(WIN_SUSP);				/* restore screen */
X	setup_tty(TTY_SUSP);			/* put tty back to normal */
X	sigvec(SIGTSTP, &nosigstr, 0); 	/* put default action back */
X	sigsetmask(0);					/* unblock "suspend" signal */
X	kill(0, SIGTSTP);				/* suspend this process */
X
X/* ----- process gets suspended here ----- */
X
X	sigvec(SIGTSTP, &stpsigstruc, 0);	/* restore local handling of "stop" signal */
X	setup_tty(TTY_RESUME);				/* restore tty */
X	buff_mod = 0;						/* set whole screen modified */
X	if (win_data[7])			/* redraw window */
X		{
X		window(WIN_RESUME);		/* re-enable window */
X		window(WIN_REDRAW);		/* force complete redraw */
X		window(WIN_REFR);		/* and refresh */
X		}
X	qio_char('\0');				/* wake up the input
X	if (exitflag) retype_cmdstr('*');	/* if not executing, prompt again and echo command string so far */
X	}
X#endif
X
X
X
X/* simulate a character's having been typed on the keyboard */
X
Xqio_char(c)
X	char c;
X	{
X	ioctl(fileno(stdin), TIOCSTI, &c);				/* send char to input stream */
X	}
X/* routine to handle "hangup" signal */
X#ifndef DEBUG
X
Xhup_handler()
X	{
X	if (!exitflag) exitflag = -3;					/* if executing, set flag to terminate */
X	else
X		{
X		panic();									/* dump buffer and close output files */
X		exit(1);
X		}
X	}
X#endif
X
X
X
X/* type a crlf */
X
Xcrlf()
X	{
X	type_char(CR);
X	type_char(LF);
X	}
X
X
X
X/* reset ^O status */
X
Xint lflusho = LFLUSHO;
Xint lfo;
X
Xreset_ctlo()
X	{
X	ioctl(fileno(stdin), TIOCLGET, &lfo);		/* read flags */
X	if (lfo & LFLUSHO)							/* if ^O was set */
X		{
X		ioctl(fileno(stdin), TIOCLBIC, &lflusho);	/* reset ^O */
X		crlf();										/* type a crlf */
X		}
X	}
X/* routine to type one character */
X
Xtype_char(c)
X	char c;
X	{
X
X	if ((char_count >= WN_width) && (c != CR) && !(spec_chars[c] & A_L))	/* spacing char beyond end of line */
X		{
X		if (et_val & ET_TRUNC) return;		/* truncate output to line width */
X		else crlf();						/* otherwise do automatic new line (note recursive call to type_char) */
X		}
X
X	if ((c & 0140) == 0)				/* control char? */
X		{
X		switch (c & 0177)
X			{
X			case CR:
X				putchar(c);
X				char_count = 0;
X				break;
X
X			case LF:
X				putchar(c);
X/*				scroll_dly();			/* filler chars in case VT-100 scrolls */
X				break;
X
X			case ESC:
X				if ((et_val & ET_IMAGE) && !exitflag) putchar(c);
X				else
X					{
X					putchar('$');
X					char_count++;
X					}
X				break;
X
X			case TAB:
X				if ((et_val & ET_IMAGE) && !exitflag) putchar(c);
X				else for (type_char(' '); (char_count & tabmask) != 0; type_char(' '));
X				break;
X
X			default:
X				if ((et_val & ET_IMAGE) && !exitflag) putchar(c);
X				else
X					{
X					putchar('^');
X					putchar(c + 'A'-1);
X					char_count += 2;
X					}
X				break;
X			}
X		}
X	else
X		{
X		putchar(c);
X		char_count++;
X		}
X	}
X
END_OF_te_chario.c
if test 9049 -ne `wc -c <te_chario.c`; then
    echo shar: \"te_chario.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"te_defs.h\" \(11866 characters\)
if test -f te_defs.h ; then 
  echo shar: Will not over-write existing file \"te_defs.h\"
else
sed "s/^X//" >te_defs.h <<'END_OF_te_defs.h'
X/* TECO for Ultrix   Copyright 1986 Matt Fichtenbaum						*/
X/* This program and its components belong to GenRad Inc, Concord MA 01742	*/
X/* They may be copied if this copyright notice is included					*/
X
X/* te_defs.h definitions file		1/9/87	*/
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sgtty.h>
X#include <setjmp.h>
X
X#define CTL(x) (('x') & 0x1f)	/* for control chars					*/
X#define ERROR(e) longjmp(xxx, (e))
X#define BLOCKSIZE (0x10000 - 8)	/* size of memory block to allocate		*/
X#define CELLSIZE 256			/* number of characters per cell		*/
X#define CSTACKSIZE 64			/* size of command stack				*/
X#define MSTACKSIZE 64			/* size of macro stack					*/
X#define QSTACKSIZE 64			/* size of q register stack				*/
X#define ESTACKSIZE 64			/* size of expression stack				*/
X#define TTIBUFSIZE 1024			/* size of type-ahead buffer			*/
X#define BUFF_LIMIT 16384		/* text buffer soft limit for ED & 4	*/
X#define NQREGS 36				/* number of Q registers				*/
X#define CBUFF 0					/* id for command buffer				*/
X#define SERBUF NQREGS+1			/* and search string buffer				*/
X#define FILBUF NQREGS+2			/* and file string buffer				*/
X#define SYSBUF NQREGS+3			/* and system command buffer			*/
X#define TIMBUF NQREGS+4			/* and time/date buffer					*/
X#define cbuf qreg[CBUFF] 		/* shorthand for command-string header	*/
X#define sbuf qreg[SERBUF]		/* and for search-buffer header			*/
X#define fbuf qreg[FILBUF]		/* and for file-buffer header			*/
X#define sysbuf qreg[SYSBUF]		/* and for system command header		*/
X#define timbuf qreg[TIMBUF]		/* and for time/date header				*/
X#define cptr (*msp)				/* command string is top of macro stack	*/
X#define cmdstr mstack[0] 		/* for entering command string			*/
X#define TAB 011					/* define special chars					*/
X#define LF 012
X#define VT 013
X#define FF 014
X#define CR 015
X#define ESC 033
X#define DEL 0177
X
X/* expression operators */
X#define OP_START 1
X#define OP_ADD	2
X#define OP_SUB	3
X#define OP_MULT	4
X#define OP_DIV	5
X#define OP_AND	6
X#define OP_OR	7
X
X/* macro flags */
X#define F_ITER	1
X
X/* bits in special-character table */
X#define A_S 1					/* "skipto()" special character		*/
X#define A_T 2					/* command with std text argument	*/
X#define A_E 4					/* E<char> takes a text argument	*/
X#define A_F 8					/* F<char> takes a text argument	*/
X#define A_X 16					/* char causes "skipto()" to exit	*/
X#define A_Q 32					/* command with q-register argument	*/
X#define A_A 64					/* special char in search string	*/
X#define A_L 128					/* character is a line separator	*/
X
X/* error codes */
X#define E_BNI 1
X#define E_CPQ 2
X#define E_COF 3
X#define E_FNF 4
X#define E_IEC 5
X#define E_IFC 6
X#define E_IIA 7
X#define E_ILL 8
X#define E_ILN 9
X#define E_IPA 10
X#define E_IQC 11
X#define E_IQN 12
X#define E_IRA 13
X#define E_ISA 14
X#define E_ISS 15
X#define E_IUC 16
X#define E_MEM 17
X#define E_MRP 18
X#define E_NAB 19
X#define E_NAC 20
X#define E_NAE 21
X#define E_NAP 22
X#define E_NAQ 23
X#define E_NAS 24
X#define E_NAU 25
X#define E_NFI 26
X#define E_NFO 27
X#define E_NYA 28
X#define E_OFO 29
X#define E_PDO 30
X#define E_POP 31
X#define E_SNI 32
X#define E_SRH 33
X#define E_STL 34
X#define E_UTC 35
X#define E_UTM 36
X#define E_XAB 37
X#define E_YCA 38
X#define E_IWA 39
X#define E_NFR 40
X#define E_INT 41
X#define E_EFI 42
X#define E_IAA 43
X#define E_AMB 44
X#define E_SYS 45
X
X/* define names for window control registers */
X#define WN_type win_data[0]
X#define WN_width win_data[1]
X#define WN_height win_data[2]
X#define WN_seeall win_data[3]
X#define WN_mark win_data[4]
X#define WN_hold win_data[5]
X#define WN_origin win_data[6]
X#define WN_scroll win_data[7]
X
X/* define display operations */
X#define WIN_OFF 0			/* disable window	*/
X#define WIN_SUSP 1			/* suspend window	*/
X#define WIN_INIT 2			/* turn on window	*/
X#define WIN_RESUME 3		/* re-enable window	*/
X#define WIN_REFR 4			/* refresh window	*/
X#define WIN_LINE 5			/* display one line */
X#define WIN_REDRAW 6		/* force window absolute redraw on next refresh */
X#define WIN_DISP 7			/* refresh window even if not enabled */
X
X/* define scope special functions */
X#define VT_CLEAR 0			/* clear screen */
X#define VT_EEOL 1			/* erase to eol	*/
X#define VT_SETSPEC1 2		/* set special (reverse) video */
X#define VT_SETSPEC2 3		/* alternative special video */
X#define VT_CLRSPEC 4		/* clear it */
X#define VT_BS1 5			/* backspace and erase 1 */
X#define VT_BS2 6			/* backspace and erase 2 */
X#define VT_LINEUP 7			/* up one line */
X#define VT_EBOL 8			/* erase from bol */
X
X/* define keyboard modes */
X#define TTY_OFF 0			/* final "off" */
X#define TTY_SUSP 1			/* temporary suspend */
X#define TTY_ON 2			/* initial "on" */
X#define TTY_RESUME 3		/* resume after suspend */
X
X/* define values for ED, ET, EZ flags */
X#define ED_CARET 1
X#define ED_YPROT 2
X#define ED_EXPMEM 4
X#define ED_SFAIL 16
X#define ED_SMULT 64
X
X#define ET_IMAGE 1
X#define ET_NOECHO 8
X#define ET_CTRLO 16
X#define ET_NOWAIT 32
X#define ET_QUIT 128
X#define ET_TRUNC 256
X#define ET_CTRLC 32768
X
X#define EZ_CRLF 1
X#define EZ_READFF 2
X#define EZ_TAB4 4
X#define EZ_NOTMPFIL 8
X#define EZ_NOTABI 16
X#define EZ_NOVTFF 32
X#define EZ_MULT 64
X/* define buffer cell */
X/* a buffer cell is a forward pointer, a backward pointer, */
X/* and CELLSIZE characters */
X
Xstruct buffcell
X	{
X	struct buffcell *f;		/* forward pointer	*/
X	struct buffcell *b;		/* backward pointer	*/
X	char ch[CELLSIZE];		/* char storage		*/
X	};
X
X/* define structures for buffer header, q-register header,			*/
X/* q-register pointer, macro stack entry, and macro iteration list	*/
X/* these are really alternative ways of looking at the same cell	*/
X
Xstruct qh			/* q-register header */
X	{
X	struct buffcell *f;	/* forward pointer */
X	struct buffcell *b;	/* backward pointer */
X	int z;				/* number of characters */
X	int v;				/* q-register numeric value */
X	} ;
X
Xstruct qp			/* q-register pointer/macro stack entry */
X	{
X	struct qp *f;		/* forward pointer */
X	struct buffcell *p;	/* pointer to a buffer cell */
X	int c;				/* character offset */
X	int z;				/* number of characters in object pointed to */
X	int dot;			/* current character position */
X	int flag;			/* flags for "iteration in process," "ei macro," etc. */
X	struct is *il;		/* iteration list pointer */
X	int *condsp;		/* saved conditional stack pointer */
X	} ;
X
Xstruct is			/* macro iteration list entry */
X	{
X	struct is *f;		/* forward pointer */
X	struct is *b;		/* backward pointer */
X	struct buffcell *p;	/* cell with start of iteration */
X	int c;				/* char offset where iteration started */
X	int dot;			/* char position where iteration started */
X	int count;			/* iteration count */
X	int dflag;			/* definite iteration flag */
X	} ;
X
Xstruct ms			/* macro stack entry */ /* not used at present */
X	{
X	struct ms *f;		/* forward pointer */
X	struct ms *b;		/* backward pointer */
X	struct buffcell *p;	/* pointer to a buffer cell */
X	int c;				/* character offset */
X	struct is *il;		/* pointer to iteration list */
X	} ;
X
Xstruct bh			/* buffer header list entry */
X	{
X	struct buffcell *f;	/* pointer to buffer */
X	struct buffcell *b;	/* null pointer */
X	int z;				/* number of characters */
X	int v;				/* not used */
X	struct bh *ff;		/* forward pointer */
X	struct bh *bb;		/* backward pointer */
X	} ;
X
X/* define expression stack entry */
Xstruct exp_entry
X	{
X	int val1;		/* first value							*/
X	int flag1;		/* nonzero if there is a first value	*/
X	int val2;		/* second value (set by 'comma')		*/
X	int flag2;		/* nonzero if there is one				*/
X	int exp;		/* expression in process				*/
X	int op;			/* operation to be applied 				*/
X	} ;
X
X/* define file data structures */
Xstruct infiledata				/* structure of input file info */
X	{
X	FILE *fd;						/* file pointer */
X	int eofsw;						/* end-of-file switch */
X	} ;
X
Xstruct outfiledata				/* structure of output file info */
X	{
X	FILE *fd;						/* file pointer */
X	char f_name[CELLSIZE+5];		/* real name of output */
X	char t_name[CELLSIZE+5];		/* temporary output name */
X	int name_size;					/* number of chars in name */
X	int bak;						/* backup flag */
X	} ;
X
Xextern struct infiledata *infile;		/* pointer to currently active intput file structure */
Xextern struct outfiledata *outfile;		/* pointer to currently active output file structure */
Xextern struct outfiledata po_file, so_file;		/* output file descriptors */
X/* define global variables, etc. */
X
Xextern int char_count;					/* char count for tab typer			*/
Xextern char lastc;						/* last char read					*/
Xextern int ttyerr;						/* error return from ioctl			*/
Xextern int errno;						/* system error code				*/
Xextern struct sgttyb ttybuf;			/* local copy of tty control data	*/
Xextern int inp_noterm;					/* nonzero if standard in is not a terminal	*/
Xextern int out_noterm;					/* nonzero if standard out is not a term.	*/
Xextern jmp_buf xxx;						/* preserved environment for error restart	*/
Xextern int err;							/* local error code					*/
Xextern struct qp t_qp;					/* temporary buffer pointer			*/
Xextern struct qp aa, bb, cc;			/* more temporaries					*/
Xextern struct buffcell t_bcell;			/* temporary bcell					*/
Xextern int tabmask;						/* mask for selecting 4/8 char tabs	*/
Xextern int exitflag;					/* flag for ending command str exec	*/
Xextern char term_char;					/* terminator for insert, search, etc.	*/
Xextern char cmdc;						/* current command character		*/
Xextern char skipc;						/* char found by "skipto()"			*/
Xextern int dot, z, tdot;				/* current, last, temp buffer position	*/
Xextern int ll, mm, nn;					/* general temps					*/
Xextern int ins_count;					/* count of chars inserted			*/
Xextern int ctrl_e;						/* form feed flag					*/
Xextern int ctrl_r;						/* current number radix (8, 10, 16)	*/
Xextern int ctrl_s;						/* string length for S, I, G		*/
Xextern int ctrl_x;						/* search case flag					*/
Xextern int ed_val;						/* ED value							*/
Xextern int es_val;						/* ES value							*/
Xextern int et_val;						/* ET value							*/
Xextern int eu_val;						/* EU value							*/
Xextern int ev_val;						/* EV value							*/
Xextern int ez_val;						/* EZ value							*/
Xextern int srch_result;					/* result of last :S executed		*/
Xextern int atflag;						/* flag for @ char typed			*/
Xextern int colonflag;					/* flag for : char typed			*/
Xextern int trace_sw;					/* nonzero if tracing command exec	*/
X
Xextern int win_data[];					/* window control parameters		*/
Xextern struct buffcell *insert_p;		/* pointer to temp text buffer during insert */
Xextern int buff_mod;					/* set to earliest buffer change	*/
Xextern int search_flag;					/* set nonzero by search			*/
X
Xextern char *errors[];					/* error text						*/
Xextern char mapch[], mapch_l[];			/* char mapping tables				*/
Xextern char spec_chars[];				/* special character table			*/
X
Xextern char skipto(), find_endcond(), getcmdc(), getcmdc0();	/* routines that return chars */
X
Xextern FILE *eisw;						/* indirect command file pointer	*/
Xextern FILE *fopen();
X
Xextern struct buffcell *freebuff;		/* buffcell free-list pointer	*/
Xextern struct buffcell *dly_freebuff;	/* delayed free-list pointer	*/
Xextern struct qp *freedcell;			/* cell free-list pointer		*/
Xextern struct buffcell *get_bcell();	/* get buffcell routine			*/
Xextern struct qp *get_dcell();			/* get data cell routine		*/
X
X/* the text buffer header */
Xextern struct qh buff;
X
X/* the q-register headers point to the start of the buffer and registers */
Xextern struct qh qreg[];			/* for q regs, command, search, file */
X
X/* the q-register stack contains temporary copies of q-register contents */
Xextern struct qh qstack[];			/* q-reg stack */
Xextern struct qh *qsp;				/* q-reg stack pointer */
X
X/* the macro stack contains pointers to the currently active macros. */
X/* the top of the stack is the command pointer */
Xextern struct qp mstack[];			/* macro stack */
Xextern struct qp *msp;				/* macro stack pointer */
X
X/* the expression stack */
Xextern struct exp_entry estack[];	/* expression stack */
Xextern struct exp_entry *esp;		/* expression stack pointer */
X
END_OF_te_defs.h
if test 11866 -ne `wc -c <te_defs.h`; then
    echo shar: \"te_defs.h\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"te_srch.c\" \(14562 characters\)
if test -f te_srch.c ; then 
  echo shar: Will not over-write existing file \"te_srch.c\"
else
sed "s/^X//" >te_srch.c <<'END_OF_te_srch.c'
X/* TECO for Ultrix   Copyright 1986 Matt Fichtenbaum						*/
X/* This program and its components belong to GenRad Inc, Concord MA 01742	*/
X/* They may be copied if this copyright notice is included					*/
X
X/* te_srch.c   routines associated with search operations   2/5/86 */
X#include "te_defs.h"
X
X/* routine to read in a string with string-build characters */
X/* used for search, tag, file name operations				*/
X/* returns 0 if empty string entered, nonzero otherwise		*/
X
Xint build_string(buff)
X	struct qh *buff;			/* arg is addr of q-reg header */
X	{
X	int count;					/* char count */
X	struct buffcell *tp;		/* pointer to temporary string */
X	char c;						/* temp character */
X
X	term_char = (atflag) ? getcmdc(trace_sw) : ESC;		/* read terminator */
X	count = atflag = 0;			/* initialize char count */
X	if (!peekcmdc(term_char))	/* if string is not empty */
X		{
X
X/* create a temporary string and read chars into it until the terminator */
X		for (tp = bb.p = get_bcell(), bb.c = 0; (c = getcmdc(trace_sw)) != term_char; )
X			{
X			if ((c == '^') && !(ed_val & ED_CARET))		/* read next char as CTL */
X				{
X				if ((c = getcmdc(trace_sw)) == term_char) ERROR(msp <= &mstack[0] ? E_UTC : E_UTM);
X				c &= 0x1f;
X				}
X			if ((c &= 0177) < ' ')			/* if a control char */
X				{
X				switch (c)
X					{
X					case CTL (Q):			/* take next char literally */
X					case CTL (R):
X						if ((c = getcmdc(trace_sw)) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
X						break;				/* fetch character and go store */
X
X					case CTL (V):			/* take next char as lower case */
X						if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
X						c = mapch_l[cmdc];
X						break;
X
X					case CTL (W):			/* take next char as upper case */
X						if ((c = getcmdc(trace_sw)) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
X						if (islower(c)) c = toupper(c);
X						break;
X
X					case CTL (E):			/* expanded constructs */
X						if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
X						switch (mapch_l[cmdc])
X							{
X							case 'u':		/* use char in q-reg */
X								if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
X								c = qreg[getqspec(1, cmdc)].v & 0x7f;
X								break;
X
X							case 'q':		/* use string in q-reg */
X								if (getcmdc(trace_sw) == term_char) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
X								ll = getqspec(1, cmdc);			/* read the reg spec */
X								aa.p = qreg[ll].f;				/* set a pointer to it */
X								aa.c = 0;
X								for (mm = 0; mm < qreg[ll].z; mm++)
X									{
X									bb.p->ch[bb.c] = aa.p->ch[aa.c];		/* store char */
X									fwdcx(&bb);					/* store next char */
X									fwdc(&aa);
X									++count;
X									}
X								continue;				/* repeat loop without storing */
X
X							default:
X								bb.p->ch[bb.c] = CTL (E);		/* not special: store the ^E */
X								fwdcx(&bb);
X								++count;
X								c = cmdc;						/* and go store the following char */
X								break;
X
X							}							/* end ^E switch */
X						}							/* end outer switch */
X				}							/* end "if a control char */
X			bb.p->ch[bb.c] = c;			/* store character */
X			fwdcx(&bb);					/* advance pointer */
X			++count;					/* count characters */
X			}						/* end "for" loop */
X		free_blist(buff->f);		/* return old buffer */
X		buff->f = tp;				/* put in new one */
X		buff->f->b = (struct buffcell *) buff;
X		buff->z = count;			/* store count of chars in string */
X		}					/* end non-null string */
X	else getcmdc(trace_sw);		/* empty string: consume terminator */
X	return(count);			/* return char count */
X	}			
X
X
X
X
X/* routine to handle end of a search operation	*/
X/* called with pass/fail result from search		*/
X/* returns same pass/fail result				*/
X
Xint end_search(result)
X	int result;
X	{
X	if (!result)		/* if search failed */
X		{
X		if (!(esp->flag2 || (ed_val & ED_SFAIL))) dot = 0;		/* if an unbounded search failed, clear ptr */
X		if (!colonflag && !peekcmdc(';')) ERROR(E_SRH);		/* if no real or implied colon, error if failure */
X		}
X	esp->flag1 = colonflag;				/* return a value if a :S command */
X	srch_result = esp->val1 = result;	/* and leave it for next ";" */
X	esp->flag2 = colonflag = atflag = 0;	/* consume arguments */
X	esp->op = OP_START;
X	return(result);
X	}
X
X/* routine to set up for search operation */
X/* reads search arguments, returns search count */
X
Xstatic struct qp sm, sb;		/* match-string and buffer pointers */
Xstatic char *pmap;				/* pointer to character mapping table */
Xstatic int locb;				/* reverse search limit */
Xstatic int last_z;				/* end point for reverse search */
X
Xint setup_search()
X	{
X	int count;				/* string occurrence counter */
X
X	set_pointer(dot, &aa);			/* set a pointer to start of search */
X	if (colonflag >= 2) esp->flag2 = esp->flag1 = esp->val2 = esp->val1 = 1;	/* ::S is 1,1S */
X	if ((count = get_value(1)) == 0) ERROR(E_ISA);	 /* read search count: default is 1 */
X	else if (count > 0)				/* search forward */
X		{
X		if (esp->flag2)		/* if bounded search */
X			{
X			if (esp->val2 < 0) esp->val2 = -(esp->val2);	/* set limit */
X			if ((aa.z = dot + esp->val2) > z) aa.z = z;		/* or z, whichever less */
X			}
X		else aa.z = z;
X		}
X	else
X		{
X		if (esp->flag2)		/* if bounded search */
X			{
X			if (esp->val2 < 0) esp->val2 = -(esp->val2);	/* set limit */
X			if ((locb = dot - esp->val2) < 0) locb = 0;		/* or 0, whichever greater */
X			}
X		else locb = 0;
X		}
X	return(count);
X	}
X
X/* routine to do N, _, E_ searches:  search, if search fails, then get	*/
X/* next page and continue 												*/
X
Xdo_nsearch(arg)
X	char arg;		/* arg is 'n', '_', or 'e' to define which search */
X	{
X	int scount;		/* search count */
X
X	build_string(&sbuf);			/* read the search string */
X	if ((scount = get_value(1)) <= 0) ERROR(E_ISA);		/* count must be >0 */
X	set_pointer(dot, &aa);			/* start search at dot */
X	esp->flag2 = locb = 0;			/* make it unbounded */
X
X	while (scount > 0)				/* search until found */
X		{
X		if (!do_search(1))			/* search forwards */
X			{						/*   if search fails... */
X			if (infile->eofsw || !infile->fd) break;	/* if no input, quit */
X			if (arg == 'n')
X				{
X				set_pointer(0, &aa);	/* write file if 'n' */
X				write_file(&aa, z, ctrl_e);
X				}
X
X			/* not 'n': if _, and an output file, and data to lose, error */
X			else if ((arg == '_') && (outfile->fd) && (z) && (ed_val & ED_YPROT)) ERROR(E_YCA);
X
X			buff_mod = dot = z = 0;				/* clear buffer */
X			set_pointer(0, &aa);
X			read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) );			/* read next page */
X			set_pointer(0, &aa);		/* search next page from beginning */
X			}
X		else --scount;					/* search successful: one fewer to look for */
X		}
X	return( end_search( (scount == 0) ? -1 : 0) );		/* use end_search to clean up */
X	}
X
X
X/* routine to do "FB" search - m,nFB is search from m to n,	*/
X/* nFB is search from . to nth line							*/
X/* convert arguments to args of normal m,nS command			*/
X
Xint do_fb()				/* returns search result */
X	{
X	if (esp->flag1 && esp->flag2)	/* if two arguments */
X		{
X		dot = esp->val2;						/* start from "m" arg */
X		esp->val2 = esp->val1 - esp->val2;		/* get number of chars */
X		}
X	else							/* if no or one args, treat as number of lines */
X		{
X		esp->val2 = lines(get_value(1));		/* number of chars */
X		esp->flag2 = esp->flag1 = 1;			/* conjure up two args */
X		}
X	esp->val1 = (esp->val2 > 0) ? 1 : -1;	/* set search direction */
X
X	build_string(&sbuf);		/* read search string and terminator */
X	return(end_search(  do_search( setup_search() )  ));	/* do search and return result */
X	}
X
X/* routine to do search operation: called with search count as argument */
X/* returns -1 (pass) or 0 (fail)										*/
X
Xint do_search(count)
X	int count;
X	{
X	pmap = (ctrl_x) ? &mapch[0] : &mapch_l[0];		/* set approp. mapping table */
X	sm.z = sbuf.z;					/* copy # of chars in search buffer */
X
X	if (count > 0)
X		{
X		for (sm.dot = 0; count > 0; count--)	 /* loop to count occurrences */
X			{
X			for (; aa.dot < aa.z; aa.dot++)	 /* loop to advance search pointer */
X				{
X				for (sb.p = aa.p, sb.c = aa.c, sb.dot = aa.dot, sm.p = sbuf.f, sm.dot = sm.c = 0;
X											(sb.dot < z) && (sm.dot < sm.z); sm.dot++, sb.dot++)
X					{								/* for each char in search string */
X					if (spec_chars[ sm.p->ch[sm.c] ] & A_A)		/* if search string char is "special" */
X						{
X						if (!srch_cmp()) break;			/* then use expanded comparison routine */
X						}
X					else if (*(pmap + sb.p->ch[sb.c]) != *(pmap + sm.p->ch[sm.c])) break;		/* else just compare */
X					if (++sm.c > CELLSIZE-1)		/* advance search-string ptr */
X						{
X						sm.p = sm.p->f;
X						sm.c = 0;
X						}
X					if (++sb.c > CELLSIZE-1)		/* advance buffer ptr */
X						{
X						sb.p = sb.p->f;
X						sb.c = 0;
X						}
X					}					/* end comparison loop */
X
X				if (sm.dot >= sm.z) break;			/* exit if found */
X				if (++aa.c > CELLSIZE-1)			/* else not found: advance buffer pointer */
X					{
X					aa.p = aa.p->f;
X					aa.c = 0;
X					}
X				}						/* end search loop */
X
X			if (sm.dot < sm.z) break;				/* if one search failed, don't do more */
X			else
X				{
X				ctrl_s = aa.dot - sb.dot;			/* otherwise save -length of string found */
X				if ((ed_val & ED_SMULT) && (count > 1))		/* if funny "advance by 1" mode */
X					{
X					++aa.dot;						/* advance buffer pointer by one only */
X					if (++aa.c > CELLSIZE-1)
X						{
X						aa.p = aa.p->f;
X						aa.c = 0;
X						}
X					}
X				else
X					{
X					aa.dot = sb.dot;				/* advance search pointer past string */
X					aa.p = sb.p;
X					aa.c = sb.c;
X					}
X				}
X			}					/* end "search n times" */
X		}				/* end "search forwards" */
X
X	else 				/* search backwards */
X		{
X		for (last_z = z, sm.dot = 0; count < 0; count++)	 /* loop to count occurrences */
X			{
X			for (; aa.dot >= locb; aa.dot--)	 /* loop to advance (backwards) search pointer */
X				{
X				for (sb.p = aa.p, sb.c = aa.c, sb.dot = aa.dot, sm.p = sbuf.f, sm.dot = sm.c = 0;
X												(sb.dot < last_z) && (sm.dot < sm.z); sm.dot++, sb.dot++)
X					{								/* loop to compare string */
X					if (spec_chars[ sm.p->ch[sm.c] ] & A_A)		/* if search string char is "special" */
X						{
X						if (!srch_cmp()) break;		/* then use expanded comparison routine */
X						}
X					else if (*(pmap + sb.p->ch[sb.c]) != *(pmap + sm.p->ch[sm.c])) break;		/* else just compare */
X					if (++sm.c > CELLSIZE-1)		/* advance search-string ptr */
X						{
X						sm.p = sm.p->f;
X						sm.c = 0;
X						}
X					if (++sb.c > CELLSIZE-1)		/* advance buffer ptr */
X						{
X						sb.p = sb.p->f;
X						sb.c = 0;
X						}
X					}					/* end comparison loop */
X				if (sm.dot >= sm.z)					/* search matches: */
X					{
X					if (!(ed_val & ED_SMULT)) last_z = aa.dot;	/* set last_z to point where this string was found */
X					break;
X					}
X				if (sb.dot >= last_z)				/* or if string is beyond end of buffer */
X					{
X					sm.dot = sm.z;						/* make search appear to have succeeded */
X					--count;							/* so as to back up pointer, and force one more look */
X					break;
X					}
X				if (--aa.c < 0)				/* else advance buffer pointer (backwards) */
X					{
X					aa.p = aa.p->b;
X					aa.c = CELLSIZE-1;
X					}
X				}						/* end search loop */
X			if (sm.dot < sm.z) break;				/* if one search failed, don't do more */
X			else
X				{
X				if (count < -1) backc(&aa);			/* if this is not last search, back pointer up one */
X				else					
X					{
X					ctrl_s = aa.dot - sb.dot;		/* otherwise save -length of string found */
X					aa.dot = sb.dot;				/* advance pointer past string */
X					aa.p = sb.p;
X					aa.c = sb.c;
X					}
X				}
X			}					/* end "search n times" */
X		}				/* end "search backwards" */
X	if (sm.dot >= sm.z) dot = aa.dot;				/* if search succeeded, update pointer	*/
X	search_flag = 1;								/* set "search occurred" (for ES)		*/
X	return((sm.dot >= sm.z) ? -1 : 0);				/* and return -1 (pass) or 0 (fail)		*/
X	}				/* end "do_search" */
X
X/* expanded search comparison */
X/* returns 1 if match, 0 if not */
X
Xint srch_cmp()
X	{
X	int tq;						/* q-reg name for ^EGq */
X	struct qp tqp;				/* pointer to read q reg */
X
X	switch (mapch_l[sm.p->ch[sm.c]])		/* what is search character */
X		{
X		case CTL (N):				/* match anything but following construct */
X			if (sm.dot >= sm.z) ERROR(E_ISS);	/* don't read past end of string */
X			fwdc(&sm);				/* skip the ^N */
X			return(!srch_cmp());
X
X		case CTL (X):				/* match any character */
X			return(1);
X
X		case CTL (Q):				/* take next char literally */
X		case CTL (R):
X			if (sm.dot >= sm.z) ERROR(E_ISS);	/* don't read past end of string */
X			fwdc(&sm);				/* skip the ^Q */
X			return(*(pmap + sb.p->ch[sb.c]) == *(pmap + sm.p->ch[sm.c]));
X
X		case CTL (S):				/* match any nonalphanumeric */
X			return(!isalnum(sb.p->ch[sb.c]));
X
X		case CTL (E):
X			if (sm.dot >= sm.z) ERROR(E_ISS);	/* don't read past end of string */
X			fwdc(&sm);				/* skip the ^E */
X			switch (mapch_l[sm.p->ch[sm.c]])
X				{
X				case 'a':			/* match any alpha */
X					return(isalpha(sb.p->ch[sb.c]));
X
X				case 'b':			/* match any nonalpha */
X					return(!isalnum(sb.p->ch[sb.c]));
X
X				case 'c':			/* rad50 symbol constituent */
X					return(!isalnum(sb.p->ch[sb.c]) || (sb.p->ch[sb.c] == '$') || (sb.p->ch[sb.c] == '.'));
X
X				case 'd':			/* digit */
X					return(isdigit(sb.p->ch[sb.c]));
X
X				case 'l':			/* line terminator LF, VT, FF */
X					return((sb.p->ch[sb.c] == LF) || (sb.p->ch[sb.c] == FF) || (sb.p->ch[sb.c] == VT));
X
X				case 'r':			/* alphanumeric */
X					return(isalnum(sb.p->ch[sb.c]));
X
X				case 'v':			/* lower case */
X					return(islower(sb.p->ch[sb.c]));
X
X				case 'w':			/* upper case */
X					return(isupper(sb.p->ch[sb.c]));
X
X				case 's':			/* any non-null string of spaces or tabs */
X					if (((sb.p->ch[sb.c]&0177) != ' ') && ((sb.p->ch[sb.c]&0177) != TAB)) return(0);	/* failure */
X					/* skip remaining spaces or tabs */
X					for ( fwdc(&sb); ((sb.p->ch[sb.c]&0177) == ' ') || ((sb.p->ch[sb.c]&0177) == TAB); fwdc(&sb) );
X					backc(&sb);		/* back up one char (calling routine will skip it) */
X					return(1);		/* success */
X
X				case 'g':			/* any char in specified q register */
X					if (sm.dot >= sm.z) ERROR(E_ISS);	/* don't read past end of string */
X					fwdc(&sm);		/* get to the next char */
X					tq = getqspec(1, sm.p->ch[sm.c]);		/* read q-reg spec */					
X					for (tqp.dot = tqp.c = 0, tqp.p = qreg[tq].f; tqp.dot < qreg[tq].z; fwdc(&tqp))
X						if (*(pmap + tqp.p->ch[tqp.c]) == *(pmap + sb.p->ch[sb.c])) return(1);	/* match */
X					return(0);		/* fail */
X
X				default:
X					ERROR(E_ISS);
X				}							/* end ^E constructions */
X
X		default:
X			return(*(pmap + sb.p->ch[sb.c]) == *(pmap + sm.p->ch[sm.c]));
X		}									/* end other constructions */
X	}
X
END_OF_te_srch.c
if test 14562 -ne `wc -c <te_srch.c`; then
    echo shar: \"te_srch.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"te_subs.c\" \(13995 characters\)
if test -f te_subs.c ; then 
  echo shar: Will not over-write existing file \"te_subs.c\"
else
sed "s/^X//" >te_subs.c <<'END_OF_te_subs.c'
X/* TECO for Ultrix   Copyright 1986 Matt Fichtenbaum						*/
X/* This program and its components belong to GenRad Inc, Concord MA 01742	*/
X/* They may be copied if this copyright notice is included					*/
X
X/* te_subs.c subroutines  11/8/85 */
X#include "te_defs.h"
X
X/* routines to copy a string of characters		*/
X/* movenchars(from, to, n)						*/
X/*  	from, to are the addresses of qps		*/
X/*    n is the number of characters to move		*/
X/* moveuntil(from, to, c, &n, max)				*/
X/*	  c is the match character that ends the move */
X/*    n is the returned number of chars moved	*/
X/* max is the maximum number of chars to move	*/
X
Xmovenchars(from, to, n)
X	struct qp *from, *to;		/* address of buffer pointers */
X	register int n;				/* number of characters */
X	{
X	register struct buffcell *fp, *tp;	/* local qp ".p" pointers	*/
X	register int fc, tc;				/* local qp ".c" subscripts */
X
X	if (n != 0)
X		{
X		fp = from->p;				/* copy pointers to local registers */
X		fc = from->c;
X		tp = to->p;
X		tc = to->c;
X
X		for (; n > 0; n--)
X			{
X			tp->ch[tc++] = fp->ch[fc++];	/* move one char */
X
X			if (tc > CELLSIZE-1)	/* check current cell done */
X				{
X				if (!tp->f)		/* is there another following? */
X					{
X					tp->f = get_bcell();	/* no, add one */
X					tp->f->b = tp;
X					}
X				tp = tp->f;
X				tc = 0;
X				}
X
X			if (fc > CELLSIZE-1)	/* check current cell done */
X				{
X				if (!fp->f)		/* oops, run out of source */
X					{
X					if (n > 1) ERROR(E_UTC);	/* error if not done */
X					}
X				else {
X					fp = fp->f;		/* chain to next cell */
X					fc = 0;
X					}
X				}
X			}
X		from->p = fp;		/* restore arguments */
X		to->p = tp;
X		from->c = fc;
X		to->c = tc;
X		}
X	}
Xmoveuntil(from, to, c, n, max, trace)
X	struct qp *from, *to;		/* address of buffer pointers	*/
X	register char c;			/* match char that ends move	*/
X	int *n;						/* pointer to returned value	*/
X	int max;					/* limit on chars to move		*/
X	int trace;					/* echo characters if nonzero	*/
X	{
X	register struct buffcell *fp, *tp;	/* local qpr ".p" pointers	*/
X	register int fc, tc;				/* local qpr ".c" subscripts */
X
X	fp = from->p;				/* copy pointers to local registers */
X	fc = from->c;
X	tp = to->p;
X	tc = to->c;
X
X	for (*n = 0; fp->ch[fc] != c; (*n)++)	/* until terminating char... */
X		{
X		if (max-- <= 0) ERROR((msp <= &mstack[0]) ? E_UTC : E_UTM);
X		tp->ch[tc++] = fp->ch[fc++];	/* move one char */
X		if (trace) type_char(tp->ch[tc-1]);		/* type it out if trace mode */
X
X		if (tc > CELLSIZE-1)	/* check current cell done */
X			{
X			if (!tp->f)		/* is there another following? */
X				{
X				tp->f = get_bcell();	/* no, add one */
X				tp->f->b = tp;
X				}
X			tp = tp->f;
X			tc = 0;
X			}
X
X		if (fc > CELLSIZE-1)	/* check current cell done */
X			{
X			if (!fp->f) ERROR(E_UTC);	 /* oops, run out of source */
X			else {
X				fp = fp->f;		/* chain to next cell */
X				fc = 0;
X				}
X			}
X		}
X
X	from->p = fp;		/* restore arguments */
X	to->p = tp;
X	from->c = fc;
X	to->c = tc;
X	}
X
X/* routine to get numeric argument */
Xint get_value(d)		/* get a value, default is argument */
X	int d;
X	{
X	int v;
X
X	v = (esp->flag1) ? esp->val1 : 
X			(esp->op == OP_SUB) ? -d : d;
X	esp->flag1 = 0;		/* consume argument */
X	esp->op = OP_START;
X	return(v);
X	}
X
X
X
X
X/* routine to convert a line count */
X/* returns number of chars between dot and nth line feed */
X
Xint lines(arg)
X	register int arg;
X	{
X	register int i, c;
X	register struct buffcell *p;
X
X	for (i = dot / CELLSIZE, p = buff.f; (i > 0) && (p->f); i--) p = p->f;	/* find dot */
X	c = dot % CELLSIZE;
X	if (arg <= 0)				/* scan backwards */
X		{
X		for (i = dot; (arg < 1) && (i > 0); )		/* repeat for each line */
X			{
X			--i;				/* count characters */
X			if (--c < 0)	/* back up the pointer */
X				{
X				if (!(p = p->b)) break;
X				c = CELLSIZE - 1;
X				}
X			if ( (ez_val & EZ_NOVTFF) ? (p->ch[c] == LF) : (spec_chars[p->ch[c]] & A_L) ) ++arg;	/* if line sep found */
X			}
X		if (arg > 0) ++i;				/* if terminated on a line separator, advance over the separator */
X		}
X
X	else						/* scan forwards */
X		{
X		for (i = dot; (arg > 0) && (i < z); i++)
X			{
X			if ( (ez_val & EZ_NOVTFF) ? (p->ch[c] == LF) : (spec_chars[p->ch[c]] & A_L) ) --arg;
X			if (++c > CELLSIZE-1)
X				{
X				if (!(p = p->f)) break;
X				c = 0;
X				}
X			}			/* this will incr over the separator anyway */
X		}
X	return(i - dot);
X	}
X
X/* routine to handle args for K, T, X, etc.		*/
X/* if two args, 'char x' to 'char y'			*/
X/* if just one arg, then n lines (default 1)	*/
X/* sets a pointer to the beginning of the specd	*/
X/* string, and a char count value				*/
X
Xint line_args(d, p)
X	int d;					/* nonzero: leave dot at start */
X	struct qp *p;
X	{
X	int n;
X
X	if (esp->flag1 && esp->flag2)		/* if two args */
X		{
X		if (esp->val1 <= esp->val2)		/* in right order */
X			{
X			if (esp->val1 < 0) esp->val1 = 0;
X			if (esp->val2 > z) esp->val2 = z;
X			if (d) dot = esp->val1;		/* update dot */
X			set_pointer(esp->val1, p);	/* set the pointer */
X			esp->flag2 = esp->flag1 = 0;	/* consume arguments */
X			esp->op = OP_START;
X			return(esp->val2 - esp->val1);	/* and return the count */
X			}
X		else
X			{
X			if (esp->val2 < 0) esp->val2 = 0;
X			if (esp->val1 > z) esp->val1 = z;
X			if (d) dot = esp->val2;		/* update dot */
X			set_pointer(esp->val2, p);	/* args in reverse order */
X			esp->flag2 = esp->flag1 = 0;	/* consume arguments */
X			esp->op = OP_START;
X			return(esp->val1 - esp->val2);
X			}
X		}
X	else
X		{
X		n = lines(get_value(1));
X		if (n < -dot) n = -dot;
X		else if (n > z-dot) n = z-dot;
X		if (n >= 0) set_pointer(dot, p);
X		else
X			{
X			n = -n;
X			set_pointer(dot - n, p);
X			if (d) dot -= n;
X			}
X		return(n);
X		}
X	}
X
X/* convert character c to a q-register spec */
Xint getqspec(fors, c)	/* fors ("file or search") nonzero = allow _ or * */
X	int fors;
X	char c;
X	{
X	if (isdigit(c)) return(c - '0' + 1);
X	else if isalpha(c) return(mapch_l[c] - 'a' + 11);
X	else if (fors)
X		{
X		if (c == '_') return (SERBUF);
X		if (c == '*') return (FILBUF);
X		if (c == '%') return (SYSBUF);
X		if (c == '#') return (TIMBUF);
X		}
X	ERROR(E_IQN);
X	}
X
X
X
X/* routines to do insert operations */
X/* insert1() copies current cell up to dot into a new cell */
X/* leaves bb pointing to end of that text */
X/* insert2() copies rest of buffer */
X
Xstruct buffcell *insert_p;
X
Xinsert1()
X	{
X	int nchars;				/* number of chars in cell */
X
X	set_pointer(dot, &aa);	/* convert dot to a qp */
X	if (dot < buff_mod) buff_mod = dot;		/* update earliest char loc touched */
X	insert_p = bb.p = get_bcell();		/* get a new cell */
X	bb.c = 0;
X	nchars = aa.c;			/* save char position of dot in cell */
X	aa.c = 0;
X
X/* now aa points to the beginning of the buffer cell that */
X/* contains dot, bb points to the beginning of a new cell,*/
X/* nchars is the number of chars before dot */
X
X	movenchars(&aa, &bb, nchars);	/* copy cell up to dot */
X	}
X
X
X
Xinsert2(count)				/* count is the number of chars added */
X	int count;
X	{
X	aa.p->b->f = insert_p;		/* put the new cell where the old one was */
X	insert_p->b = aa.p->b;
X	insert_p = NULL;
X
X	bb.p->f = aa.p;			/* splice rest of buffer to end */
X	aa.p->b = bb.p;
X	movenchars(&aa, &bb, z-dot);	/* squeeze buffer */
X	free_blist(bb.p->f);	/* return unused cells */
X	bb.p->f = NULL;			/* and end the buffer */
X	z += count;				/* add # of chars inserted */
X	dot += count;
X	ctrl_s = -count;		/* save string length */
X	}
X
X/* subroutine to delete n characters starting at dot	*/
X/* argument is number of characters						*/
X
Xdelete1(nchars)
X	int nchars;
X	{
X	if (!nchars) return;		/* 0 chars is a nop */
X	if (nchars < 0)		/* delete negative number of characters? */
X		{
X		nchars = -nchars;			/* make ll positive */
X		if (nchars > dot) ERROR(E_POP);		/* don't delete beyond beg of buffer */
X		dot -= nchars;				/* put pointer before deleted text */
X		}
X	else if (dot + nchars > z) ERROR(E_POP);	/* don't delete beyond end of buffer */
X
X	set_pointer(dot, &aa);			/* pointer to beginning of area to delete */
X	set_pointer(dot+nchars, &bb);	/* and to end */
X	if (dot < buff_mod) buff_mod = dot;		/* update earliest char loc touched */
X	movenchars(&bb, &aa, z-(dot+nchars));	/* move text unless delete ends at z */
X	free_blist(aa.p->f);			/* return any cells after end */
X	aa.p->f = NULL;					/* end the buffer */
X	z -= nchars;					/* adjust z */
X	}
X
X/* routine to process "O" command */
X
Xstruct qh obuff;		/* tag string buffer */
X
Xdo_o()
X	{
X	int i, j;			/* i used as start of tag, j as end */
X	int p, level;		/* p is pointer to tag string, level is iteration lvl */
X	int epfound;		/* flag for "second ! found"		*/
X
X	if (!build_string(&obuff)) return;		/* no tag spec'd: continue */
X	if (obuff.z > CELLSIZE) ERROR(E_STL);	/* string too long */
X	esp->op = OP_START;						/* consume any argument */
X	if (esp->flag1)							/* is there one? */
X		{
X		esp->flag1 = 0;						/* consume it */
X		if (esp->val1 < 0) return;			/* computed goto out of range - */
X		for (i = 0; (i < obuff.z) && (esp->val1 > 0); i++)		/* scan to find right tag */
X			if (obuff.f->ch[i] == ',') esp->val1--;				/* count commas */
X		if (esp->val1 > 0) return;			/* computed goto out of range + */
X
X/* now i is either at 0 or after the nth comma */
X
X		for (j = i; j < obuff.z; j++)	/* find end of tag */
X			if (obuff.f->ch[j] == ',') break;		/* stop at next comma */
X		if (j == i) return;				/* two adjacent commas: zero length tag */
X		}
X
X	else
X		{
X		i = 0;				/* not a computed goto: use whole tag buffer */
X		j = obuff.z;
X		}
X
X/* start from beginning of iteration or macro, and look for tag */
X
X	if (cptr.flag & F_ITER)			/* if in iteration */
X		{
X		cptr.p = cptr.il->p;		/* restore */
X		cptr.c = cptr.il->c;
X		cptr.dot = cptr.il->dot;
X		}
X	else for (cptr.dot = cptr.c = 0; cptr.p->b->b != NULL; cptr.p = cptr.p->b);	/* find macro start */
X
X/* search for tag */
X
X	for (level = 0; ;)			/* look through rest of command string */
X		{
X		switch (skipto(1))		/* look for interesting things, including ! */
X			{
X			case '<':			/* start of iteration */
X				++level;
X				break;
X
X			case '>':			/* end of iteration */
X				if ((level == 0) && (cptr.flag & F_ITER)) pop_iteration(1);
X				else --level;
X				break;
X
X			case '!':				/* start of tag */
X				for (epfound = 0; ; epfound = 0)		/* keep looking for tag */
X					{
X					for (p = i; p < j; p++)
X						{
X						if (getcmdc(0) == '!') epfound = 1;		/* mark "trailing ! found */
X						if (mapch_l[cmdc] != mapch_l[obuff.f->ch[p]]) break;	/* compare */
X						}
X					if (p >= j)			/* if all comparison chars matched */
X						{
X						if (getcmdc(0) == '!') return;	/* and tag ends with !, found it */
X						}
X					else if (!epfound) while (getcmdc(0) != '!');		/* else look for next ! and continue */
X					}
X				break;
X			}			/* end of switch */
X		}			/* end of scan loop */
X	}			/* end of subroutine */
X
X/* routine to skip to next ", ', |, <, or >			*/
X/* skips over these chars embedded in text strings	*/
X/* stops in ! if argument is nonzero				*/
X/* returns character found, and leaves it in skipc	*/
X
Xchar skipto(arg)
X	int arg;
X	{
X	int atsw;				/* "at" prefix */
X	char ta, term;			/* temp attributes, terminator */
X
X	for (atsw = 0; ;)		/* forever		*/
X		{
X		while (!(ta = spec_chars[skipc = getcmdc(0)] & (A_X | A_S | A_T | A_Q)));	/* read until something interesting found */
X
X	again:
X		if (ta & A_Q) getcmdc(0);		/* if command takes a Q spec, skip the spec */
X		if (ta & A_X)					/* sought char found: quit */
X			{
X			if (skipc == '"') getcmdc(0);	/* quote must skip next char */
X			return(skipc);
X			}
X		if (ta & A_S)								/* other special char */
X			{
X			switch (skipc)
X				{
X				case '^':							/* treat next char as CTL */
X					if (ta = spec_chars[skipc = getcmdc(0) & 0x1f]) goto again;
X					break;
X
X				case '@':							/* use alternative text terminator */
X					atsw = 1;
X					break;
X
X				case CTL (^):						/* ^^ is value of next char: skip that char */
X					getcmdc(0);
X					break;
X
X				case CTL (A):						/* type text */
X					term = (atsw) ? getcmdc(0) : CTL (A);
X					atsw = 0;
X					while (getcmdc(0) != term);		/* skip text */
X					break;
X
X				case '!':							/* tag */
X					if (arg) return(skipc);
X					while (getcmdc(0) != '!');		/* skip until next ! */
X					break;
X
X				case 'e':							/* first char of two-letter E or F command */
X				case 'f':
X					if (spec_chars[getcmdc(0)] & ((skipc == 'e') ? A_E : A_F)) 		/* if one with a text arg */
X						{
X						term = (atsw) ? getcmdc(0) : ESC;
X						atsw = 0;
X						while (getcmdc(0) != term);		/* read past terminator */
X						}
X					break;
X				}				/* end "switch" */
X			}				/* end "if (ta & A_S)" */
X
X		else if (ta & A_T)						/* command with a text argument */
X			{
X			term = (atsw) ? getcmdc(0) : ESC;
X			atsw = 0;
X			while (getcmdc(0) != term);			/* skip text */
X			}
X		}				/* end "forever" */
X	}				/* end "skipto()" */
X
X/* find number of characters to next matching (, [, or {  (like '%' in vi) */
X
Xdo_ctlp()
X	{
X	int i, l;
X	char c, c1;
X
X	set_pointer(dot, &aa);			/* point to text buffer */
X	switch(c1 = aa.p->ch[aa.c])
X		{
X		case '(':
X			c = ')';			/* match char is ) */
X			i = 1;				/* direction is positive */
X			break;
X
X		case ')':
X			c = '(';			/* match char is ( */
X			i = -1;				/* direction is negative */
X			break;
X
X		case '[':
X			c = ']';
X			i = 1;
X			break;
X
X		case ']':
X			c = '[';
X			i = -1;
X			break;
X
X		case '{':
X			c = '}';
X			i = 1;
X			break;
X
X		case '}':
X			c = '{';
X			i = -1;
X			break;
X
X		case '<':
X			c = '>';
X			i = 1;
X			break;
X
X		case '>':
X			c = '<';
X			i = -1;
X			break;
X
X		case '"':
X			c = '\'';
X			i = 1;
X			break;
X
X		case '\'':
X			c = '"';
X			i = -1;
X			break;
X
X		default:
X			esp->val1 = i = 0;		/* not on a matchable char, return 0 */
X		}
X
X	l = 1;			/* start with one unmatched char */
X	if (i > 0)		/* if searching forward */
X		{
X		for (i = dot, fwdc(&aa); (i < z) && (l); fwdc(&aa) )
X			{
X			++i;
X			if (aa.p->ch[aa.c] == c) --l;
X			else if (aa.p->ch[aa.c] == c1) ++l;
X			}
X		esp->val1 = (i < z) ? i - dot : 0;
X		}
X	else if (i < 0)
X		{
X		for (i = dot, backc(&aa); (i >= 0) && (l); backc(&aa) )
X			{
X			--i;
X			if (aa.p->ch[aa.c] == c) --l;
X			else if (aa.p->ch[aa.c] == c1) ++l;
X			}
X		esp->val1 = (i >= 0) ? i - dot : 0;
X		}
X	esp->flag1 = 1;
X	}
X
END_OF_te_subs.c
if test 13995 -ne `wc -c <te_subs.c`; then
    echo shar: \"te_subs.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
DONE=true
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	echo shar: You still need to run archive ${I}.
	DONE=false
    fi
done
if test "$DONE" = "true" ; then
	echo You have unpacked all 4 archives.
	echo "See the *.doc files"
	rm -f ark[1-9]isdone
fi
##  End of shell archive.
exit 0