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 }
Xmoveuntil(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