sources-request@mirror.UUCP (03/13/87)
Submitted by: genrad!mlf
Mod.sources: Volume 9, Issue 30
Archive-name: teco/Part03
#! /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 3 (of 4)."
# Contents: te_exec1.c te_exec2.c
# Wrapped by rs@mirror on Thu Mar 12 19:54:32 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"te_exec1.c\" \(21012 characters\)
if test -f te_exec1.c ; then
echo shar: Will not over-write existing file \"te_exec1.c\"
else
sed "s/^X//" >te_exec1.c <<'END_OF_te_exec1.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_exec1.c continue executing commands 1/8/87 */
X#include "te_defs.h"
X
Xexec_cmds1()
X {
X char command; /* command character */
X int cond; /* conditional in progress */
X
X switch (command = mapch_l[cmdc])
X {
X/* operators */
X
X case '+':
X esp->exp = (esp->flag1) ? esp->val1 : 0;
X esp->flag1 = 0;
X esp->op = OP_ADD;
X break;
X
X case '-':
X esp->exp = (esp->flag1) ? esp->val1 : 0;
X esp->flag1 = 0;
X esp->op = OP_SUB;
X break;
X
X case '*':
X esp->exp = (esp->flag1) ? esp->val1 : 0;
X esp->flag1 = 0;
X esp->op = OP_MULT;
X break;
X
X case '/':
X esp->exp = (esp->flag1) ? esp->val1 : 0;
X esp->flag1 = 0;
X esp->op = OP_DIV;
X break;
X
X case '&':
X esp->exp = (esp->flag1) ? esp->val1 : 0;
X esp->flag1 = 0;
X esp->op = OP_AND;
X break;
X
X case '#':
X esp->exp = (esp->flag1) ? esp->val1 : 0;
X esp->flag1 = 0;
X esp->op = OP_OR;
X break;
X
X case ')':
X if ((!esp->flag1) || (esp <= &estack[0])) ERROR(E_NAP);
X --esp;
X esp->val1 = (esp+1)->val1; /* carry value from inside () */
X esp->flag1 = 1;
X break;
X case ',':
X if (!esp->flag1) ERROR(E_NAC);
X else esp->val2 = esp->val1;
X esp->flag2 = 1;
X esp->flag1 = 0;
X break;
X
X case CTL (_):
X if (!esp->flag1) ERROR(E_NAB);
X else esp->val1 = ~esp->val1;
X break;
X
X/* radix control */
X
X case CTL (D):
X ctrl_r = 10;
X esp->flag1 = 0;
X esp->op = OP_START;
X break;
X
X case CTL (O):
X ctrl_r = 8;
X esp->flag1 = 0;
X esp->op = OP_START;
X break;
X
X case CTL (R):
X if (!esp->flag1) /* fetch it */
X {
X esp->val1 = ctrl_r;
X esp->flag1 = 1;
X }
X else
X {
X if ((esp->val1 != 8) && (esp->val1 != 10) && (esp->val1 != 16)) ERROR(E_IRA);
X ctrl_r = esp->val1;
X esp->flag1 = 0;
X esp->op = OP_START;
X }
X break;
X
X/* other commands */
X
X case CTL (C): /* 1 ^C stops macro execution, 2 exit */
X if (peekcmdc(CTL (C))) exitflag = -1; /* 2 ^C: stop execution and exit */
X else if (msp <= &mstack[0]) exitflag = 1; /* 1 ^C: in command string: stop execution */
X else --msp; /* in a macro - pop it */
X break;
X
X case CTL (X): /* search mode flag */
X set_var(&ctrl_x);
X break;
X
X case 'e':
X do_e();
X break;
X
X case 'f':
X do_f();
X break;
X/* macro call, iteration, conditional */
X
X case 'm': /* macro call */
X mm = getqspec(0, getcmdc(trace_sw)); /* read the macro name */
X if (msp > &mstack[MSTACKSIZE-1]) ERROR(E_PDO); /* check room for another level */
X ++msp; /* push stack */
X cptr.p = qreg[mm].f; /* to stack entry, put q-reg text start */
X cptr.flag = cptr.c = cptr.dot = 0; /* initial char position, iteration flag */
X cptr.z = qreg[mm].z; /* number of chars in macro */
X break;
X
X case '<': /* begin iteration */
X if ((esp->flag1) && (esp->val1 <= 0)) /* if this is not to be executed */
X find_enditer(); /* just skip the intervening stuff */
X else
X {
X if (!cptr.il) /* does this macro have an iteration list? */
X {
X cptr.il = (struct is *) get_dcell(); /* no, make one for it */
X cptr.il->b = NULL; /* with NULL reverse pointer */
X }
X else if (cptr.flag & F_ITER) /* is there an iteration in process? */
X {
X if (!cptr.il->f) /* yes, if it has no forward pointer */
X {
X cptr.il->f = (struct is *) get_dcell(); /* append a cell to the iteration list */
X cptr.il->f->b = cptr.il; /* and link it in */
X }
X cptr.il = cptr.il->f; /* and advance the iteration list pointer to it */
X }
X cptr.flag |= F_ITER; /* set iteration flag */
X cptr.il->p = cptr.p; /* save start of iteration */
X cptr.il->c = cptr.c;
X cptr.il->dot = cptr.dot;
X if (cptr.il->dflag = esp->flag1) /* if there is an argument, set the "def iter" flag */
X {
X cptr.il->count = esp->val1; /* save the count */
X esp->flag1 = 0; /* and consume the arg */
X }
X }
X break;
X
X case '>': /* end iteration */
X if (!(cptr.flag & F_ITER)) ERROR(E_BNI); /* error if > not in iteration */
X pop_iteration(0); /* decrement count and pop conditionally */
X esp->flag1 = esp->flag2 = 0; /* consume arguments */
X esp->op = OP_START;
X break;
X
X case ';': /* semicolon iteration exit */
X if (!(cptr.flag &F_ITER)) ERROR(E_SNI); /* error if ; not in iteration */
X if ( ( ((esp->flag1) ? esp->val1 : srch_result) >= 0) ? (!colonflag) : colonflag) /* if exit */
X {
X find_enditer(); /* get to end of iteration */
X pop_iteration(1); /* and pop unconditionally */
X }
X esp->flag1 = colonflag = 0; /* consume arg and colon */
X esp->op = OP_START;
X break;
X/* conditionals */
X
X case '"':
X if (!esp->flag1) ERROR(E_NAQ); /* must be an argument */
X esp->flag1 = 0; /* consume argument */
X esp->op = OP_START;
X switch (mapch_l[getcmdc(trace_sw)])
X {
X case 'a':
X cond = isalpha(esp->val1);
X break;
X
X case 'c':
X cond = isalpha(esp->val1) | (esp->val1 == '$') | (esp->val1 == '.');
X break;
X
X case 'd':
X cond = isdigit(esp->val1);
X break;
X
X case 'e':
X case 'f':
X case 'u':
X case '=':
X cond = !(esp->val1);
X break;
X
X case 'g':
X case '>':
X cond = (esp->val1 > 0);
X break;
X
X case 'l':
X case 's':
X case 't':
X case '<':
X cond = (esp->val1 < 0);
X break;
X
X case 'n':
X cond = esp->val1;
X break;
X
X case 'r':
X cond = isalnum(esp->val1);
X break;
X
X case 'v':
X cond = islower(esp->val1);
X break;
X
X case 'w':
X cond = isupper(esp->val1);
X break;
X
X default:
X ERROR(E_IQC);
X }
X if (!cond) /* if this conditional isn't satisfied */
X {
X for (ll = 1; ll > 0;) /* read to matching | or ' */
X {
X while ((skipto(0) != '"') && (skipc != '|') && (skipc != '\'')); /* skip chars */
X if (skipc == '"') ++ll; /* start another level */
X else if (skipc == '\'') --ll; /* end a level */
X else if (ll == 1) break; /* "else" (|): if on this level, start executing */
X }
X }
X break;
X
X case '\'': /* end of conditional */
X break; /* ignore it if executing */
X
X case '|': /* "else" clause */
X for (ll = 1; ll > 0;) /* skip to matching ' */
X {
X while ((skipto(0) != '"') && (skipc != '\'')); /* skip chars */
X if (skipc == '"') ++ll; /* start another level */
X else --ll; /* end a level */
X }
X break;
X/* q-register numeric operations */
X
X case 'u':
X if (!esp->flag1) ERROR(E_NAU); /* error if no arg */
X else qreg[getqspec(0, getcmdc(trace_sw))].v = esp->val1;
X esp->flag1 = esp->flag2; /* command's "value" is 2nd arg */
X esp->val1 = esp->val2;
X esp->flag2 = 0; /* clear 2nd arg */
X esp->op = OP_START;
X break;
X
X case 'q': /* Qn is numeric val, :Qn is # of chars, mQn is mth char */
X mm = getqspec((colonflag || esp->flag1), getcmdc(trace_sw)); /* read register name */
X if (!(esp->flag1))
X {
X esp->val1 = (colonflag) ? qreg[mm].z : qreg[mm].v;
X esp->flag1 = 1;
X }
X else /* esp->flag1 is already set */
X {
X if ((esp->val1 >= 0) && (esp->val1 < qreg[mm].z)) /* char subscript within range? */
X {
X for (ll = 0, aa.p = qreg[mm].f; ll < (esp->val1 / CELLSIZE); ll++) aa.p = aa.p->f;
X esp->val1 = (int) aa.p->ch[esp->val1 % CELLSIZE];
X }
X else esp->val1 = -1; /* char position out of range */
X esp->op = OP_START; /* consume argument */
X }
X colonflag = 0;
X break;
X
X case '%':
X esp->val1 = (qreg[getqspec(0, getcmdc(trace_sw))].v += get_value(1)); /* add to q reg */
X esp->flag1 = 1;
X break;
X/* move pointer */
X
X case 'c':
X if (((tdot = dot + get_value(1)) < 0) || (tdot > z))
X ERROR(E_POP); /* add arg to dot, default 1 */
X else dot = tdot;
X esp->flag2 = 0;
X break;
X
X case 'r':
X if (((tdot = dot - get_value(1)) < 0) || (tdot > z))
X ERROR(E_POP); /* add arg to dot, default 1 */
X else dot = tdot;
X esp->flag2 = 0;
X break;
X
X case 'j':
X if (((tdot = get_value(0)) < 0) || (tdot > z))
X ERROR(E_POP); /* add arg to dot, default 1 */
X else dot = tdot;
X esp->flag2 = 0;
X break;
X
X case 'l':
X dot += lines(get_value(1));
X break;
X
X/* number of chars until nth line feed */
X
X case CTL (Q):
X esp->val1 = lines(get_value(1));
X esp->flag1 = 1;
X break;
X
X/* print numeric value */
X
X case '=':
X if (!esp->flag1) ERROR(E_NAE); /* error if no arg */
X else
X {
X if (peekcmdc('=')) /* at least one more '=' */
X {
X getcmdc(trace_sw); /* read past it */
X if (peekcmdc('=')) /* another? */
X {
X getcmdc(trace_sw); /* yes, read it too */
X printf("%x", esp->val1); /* print in hex */
X }
X else printf("%o", esp->val1); /* print in octal */
X }
X else printf("%d", esp->val1);
X if (!colonflag) crlf();
X esp->flag1 = esp->flag2 = colonflag = 0;
X esp->op = OP_START;
X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
X }
X break;
X/* insert text */
X
X case TAB: /* insert tab, then text */
X if (ez_val & EZ_NOTABI) break; /* tab disabled */
X if (esp->flag1) ERROR(E_IIA); /* can't have arg */
X
X case 'i': /* insert text at pointer */
X term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */
X if (esp->flag1) /* if a nI$ command */
X {
X if (!peekcmdc(term_char)) ERROR(E_IIA); /* next char must be term */
X insert1(); /* first part of insert */
X bb.p->ch[bb.c] = esp->val1 & 0177; /* insert character */
X fwdcx(&bb); /* advance pointer and extend buffer if necessary */
X ins_count = 1; /* save string length */
X esp->op = OP_START; /* consume argument */
X }
X else /* not a nI command: insert text */
X {
X insert1(); /* initial insert operations */
X
X if (command == TAB) /* TAB insert puts in a tab first */
X {
X bb.p->ch[bb.c] = TAB; /* insert a tab */
X fwdcx(&bb); /* advance pointer and maybe extend buffer */
X }
X moveuntil(&cptr, &bb, term_char, &ins_count, cptr.z - cptr.dot, trace_sw); /* copy cmd str -> buffer */
X if (command == TAB) ++ins_count; /* add 1 if a tab inserted */
X cptr.dot += ins_count; /* indicate advance over that many chars */
X }
X insert2(ins_count); /* finish insert */
X getcmdc(trace_sw); /* flush terminating char */
X colonflag = atflag = esp->flag1 = esp->flag2 = 0; /* clear args */
X break;
X
X/* type text from text buffer */
X
X case 't':
X for (ll = line_args(0, &aa); ll > 0; ll--) /* while there are chars to type */
X {
X type_char(aa.p->ch[aa.c]);
X fwdc(&aa);
X }
X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
X break;
X
X case 'v':
X if ((ll = get_value(1)) > 0) /* arg must be positive */
X {
X mm = lines(1 - ll); /* find start */
X nn = lines(ll) - mm; /* and number of chars */
X set_pointer(dot + mm, &aa); /* pointer to start of text */
X for (; nn > 0; nn--) /* as above */
X {
X type_char(aa.p->ch[aa.c]);
X fwdc(&aa);
X }
X }
X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
X break;
X/* type text from command string */
X
X case CTL (A):
X term_char = (atflag) ? getcmdc(trace_sw) : CTL(A); /* set terminator */
X while (getcmdc(0) != term_char) type_char(cmdc); /* output chars */
X atflag = colonflag = esp->flag2 = esp->flag1 = 0;
X esp->op = OP_START;
X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
X break;
X
X /* delete text */
X
X case 'd':
X if (!esp->flag2) /* if only one argument */
X {
X delete1(get_value(1)); /* delete chars (default is 1) */
X break;
X } /* if two args, fall through to treat m,nD as m,nK */
X
X case 'k': /* delete lines or chars */
X ll = line_args(1, &aa); /* aa points to start, ll chars, leave dot at beginning */
X delete1(ll); /* delete ll chars */
X break;
X
X/* q-register text loading commands */
X
X case CTL (U):
X mm = getqspec(0, getcmdc(trace_sw));
X if (!colonflag) /* X, ^U commands destroy previous contents */
X {
X dly_free_blist(qreg[mm].f);
X qreg[mm].f = NULL;
X qreg[mm].z = 0;
X }
X term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */
X atflag = 0; /* clear flag */
X
X if ((esp->flag1) || (!peekcmdc(term_char))) /* if an arg or a nonzero insert, find register */
X {
X make_buffer(&qreg[mm]); /* attach a text buffer to the q register */
X for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f); /* find end of reg */
X bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0;
X }
X if (!(esp->flag1))
X {
X moveuntil(&cptr, &bb, term_char, &ll, cptr.z - cptr.dot, trace_sw);
X cptr.dot += ll; /* indicate advance over that many chars */
X qreg[mm].z += ll; /* update q-reg char count */
X getcmdc(trace_sw); /* skip terminator */
X }
X else
X {
X if (getcmdc(trace_sw) != term_char) ERROR(E_IIA); /* must be zero length string */
X bb.p->ch[bb.c] = esp->val1; /* store char */
X fwdcx(&bb); /* extend the register */
X ++qreg[mm].z;
X esp->flag1 = 0; /* consume argument */
X }
X colonflag = 0;
X break;
X case 'x':
X mm = getqspec(0, getcmdc(trace_sw));
X if (!colonflag) /* X, ^U commands destroy previous contents */
X {
X dly_free_blist(qreg[mm].f); /* return, but delayed (in case executing now) */
X qreg[mm].f = NULL;
X qreg[mm].z = 0;
X }
X
X if (ll = line_args(0, &aa)) /* read args and move chars, if any */
X {
X make_buffer(&qreg[mm]); /* attach a text buffer to the q register */
X for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f); /* find end of reg */
X bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0;
X
X movenchars(&aa, &bb, ll);
X qreg[mm].z += ll; /* update q-reg char count */
X }
X colonflag = 0;
X break;
X
X case 'g': /* get q register */
X if (qreg[mm = getqspec(1, getcmdc(trace_sw))].z) /* if any chars in it */
X {
X cc.p = qreg[mm].f; /* point cc to start of reg */
X cc.c = 0;
X if (colonflag) /* :Gx types q-reg */
X {
X for (ll = qreg[mm].z; ll > 0; ll--)
X {
X type_char(cc.p->ch[cc.c]); /* type char */
X fwdc(&cc);
X }
X }
X else
X {
X insert1(); /* set up for insert */
X movenchars(&cc, &bb, qreg[mm].z); /* copy q reg text */
X insert2(qreg[mm].z); /* finish insert */
X }
X }
X colonflag = 0;
X break;
X/* q-register push and pop */
X
X case '[':
X if (qsp > &qstack[QSTACKSIZE-1]) ERROR(E_PDO); /* stack full */
X else
X {
X make_buffer(++qsp); /* increment stack ptr and put a text buffer there */
X mm = getqspec(1, getcmdc(trace_sw)); /* get the q reg name */
X
X aa.p = qreg[mm].f; /* point to the q register */
X aa.c = 0;
X bb.p = qsp->f; /* point to the new list */
X bb.c = 0;
X movenchars(&aa, &bb, qreg[mm].z); /* copy the text */
X qsp->z = qreg[mm].z; /* and the length */
X qsp->v = qreg[mm].v; /* and the value */
X }
X break;
X
X case ']':
X mm = getqspec(1, getcmdc(trace_sw)); /* get reg name */
X if (qsp < &qstack[0]) /* if stack empty */
X {
X if (colonflag) /* :] returns 0 */
X {
X esp->flag1 = 1;
X esp->val1 = 0;
X colonflag = 0;
X }
X else ERROR(E_CPQ); /* ] makes an error */
X }
X else /* stack not empty */
X {
X free_blist(qreg[mm].f); /* return orig contents of reg */
X qreg[mm].f = qsp->f; /* substitute stack entry */
X qsp->f->b = (struct buffcell *) &qreg[mm];
X qsp->f = NULL; /* null out stack entry */
X qreg[mm].z = qsp->z;
X qreg[mm].v = qsp->v;
X if (colonflag)
X {
X esp->flag1 = 1; /* :] returns -1 */
X esp->val1 = -1;
X colonflag = 0;
X }
X --qsp;
X }
X break;
X case '\\':
X if (!(esp->flag1)) /* no argument; read number */
X {
X ll = esp->val1 = 0; /* sign flag and initial value */
X for (ctrl_s = 0; dot <= z; dot++, ctrl_s--) /* count digits; don't read beyond buffer */
X {
X set_pointer(dot, &aa); /* point to dot */
X if ((aa.p->ch[aa.c] == '+') || (aa.p->ch[aa.c] == '-'))
X {
X if (ll) break; /* second sign: quit */
X else ll = aa.p->ch[aa.c]; /* first sign: save it */
X }
X else
X {
X if (ctrl_r != 16) /* octal or decimal */
X { /* stop if not a valid digit */
X if ((!isdigit(aa.p->ch[aa.c])) || (aa.p->ch[aa.c] - '0' >= ctrl_r)) break;
X esp->val1 = esp->val1 * ctrl_r + (aa.p->ch[aa.c] - '0');
X }
X else
X {
X if (!isxdigit(aa.p->ch[aa.c])) break;
X esp->val1 = esp->val1 * 16 + ( (isdigit(aa.p->ch[aa.c])) ?
X aa.p->ch[aa.c] - '0' : mapch_l[aa.p->ch[aa.c]] - 'a' + 10);
X } /* end of hex */
X } /* end of digit processing */
X } /* end of "for each char" */
X if (ll == '-') esp->val1 = -(esp->val1); /* if minus sign */
X esp->flag1 = 1; /* always returns a value */
X }
X
X else /* argument: insert it as a digit string */
X {
X if (ctrl_r == 8) sprintf(t_bcell.ch, "%o", esp->val1); /* print as digits */
X else if (ctrl_r == 10) sprintf(t_bcell.ch, "%d", esp->val1);
X else sprintf(t_bcell.ch, "%x", esp->val1);
X insert1(); /* start insert */
X cc.p = &t_bcell; /* point cc to the temp cell */
X cc.c = 0;
X moveuntil(&cc, &bb, '\0', &ins_count, CELLSIZE-1, 0); /* copy the char string */
X insert2(ins_count); /* finish the insert */
X esp->flag1 = 0; /* consume argument */
X esp->op = OP_START;
X }
X break;
X case CTL (T): /* type or input character */
X if (esp->flag1) /* type */
X {
X type_char(esp->val1);
X esp->flag1 = 0;
X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
X }
X else
X {
X esp->val1 = (et_val & ET_NOWAIT) ? gettty_nowait() : gettty();
X if (!(et_val & ET_NOECHO) && (esp->val1 > 0) && !inp_noterm) type_char(esp->val1); /* echo */
X esp->flag1 = 1;
X }
X break;
X
X/* search commands */
X
X case 's': /* search within buffer */
X build_string(&sbuf); /* read the search string */
X end_search ( do_search( setup_search() ) ); /* search */
X break;
X
X case 'n': /* search through rest of file */
X case '_':
X do_nsearch(command); /* call routine for N, _, E_ */
X break;
X
X case 'o': /* branch to tag */
X do_o();
X break;
X/* file I/O commands */
X
X case 'p': /* write a page, get next (ignore args for now) */
X if (esp->flag1 && esp->flag2) /* if two args */
X write_file(&aa, line_args(0, &aa), 0); /* write spec'd buffer with no FF */
X else /* one arg */
X {
X for (ll = get_value(1); ll > 0; ll--) /* get count and loop */
X {
X set_pointer(0, &aa);
X if (peekcmdc('w')) write_file(&aa, z, 1); /* PW writes buffer, then FF */
X else
X {
X write_file(&aa, z, ctrl_e); /* P writes buffer, FF if read in, then gets next page */
X dot = z = 0; /* empty the buffer */
X set_pointer(0, &aa); /* set a pointer to the beginning of the buffer */
X buff_mod = 0; /* mark where new buffer starts */
X esp->val1 = read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) ); /* read a page */
X esp->flag1 = colonflag;
X }
X }
X }
X if (peekcmdc('w')) getcmdc(trace_sw); /* if a PW command, consume the W */
X colonflag = 0;
X break;
X
X case 'y': /* get a page into buffer */
X if (esp->flag1) ERROR(E_NYA);
X if ((z) && (!(ed_val & ED_YPROT))) ERROR(E_YCA); /* don't lose text */
X dot = z = 0; /* clear buffer */
X set_pointer(0, &aa); /* set a pointer to the beginning of the buffer */
X buff_mod = 0; /* mark where new buffer starts */
X read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) ); /* read a page */
X esp->flag1 = colonflag;
X esp->op = OP_START;
X colonflag = 0;
X break;
X case 'a': /* append, or ascii value */
X if (esp->flag1 && !colonflag) /* ascii value */
X {
X ll = dot + esp->val1; /* set a pointer before addr'd char */
X if ((ll >= 0) && (ll < z)) /* if character lies within buffer */
X {
X set_pointer(ll, &aa);
X esp->val1 = (int) aa.p->ch[aa.c]; /* get char (flag already set) */
X }
X else esp->val1 = -1; /* otherwise return -1 */
X }
X else
X {
X set_pointer(z, &aa); /* set pointer to end of buffer */
X if (z < buff_mod) buff_mod = z; /* mark where new buffer starts */
X if (esp->flag1 && (esp->val1 <= 0)) ERROR(E_IAA); /* neg or 0 arg to :A */
X read_file(&aa, &z, (esp->flag1 ? esp->val1 : 0) ); /* read a page */
X esp->flag1 = colonflag;
X colonflag = 0;
X }
X esp->op = OP_START;
X break;
X
X/* window commands */
X
X case 'w':
X do_window(0); /* this stuff is with the window driver */
X break;
X
X case CTL (W):
X do_window(1); /* this is, too */
X break;
X
X default:
X ERROR(E_ILL); /* invalid command */
X
X } /* end of "switch" */
X return; /* normal exit */
X } /* end of exec_cmds1 */
X
END_OF_te_exec1.c
if test 21012 -ne `wc -c <te_exec1.c`; then
echo shar: \"te_exec1.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"te_exec2.c\" \(29256 characters\)
if test -f te_exec2.c ; then
echo shar: Will not over-write existing file \"te_exec2.c\"
else
sed "s/^X//" >te_exec2.c <<'END_OF_te_exec2.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_exec2.c process "E" and "F" commands 2/26/87 */
X#include "te_defs.h"
X#include <sys/wait.h>
X
Xstruct qh oldcstring; /* hold command string during ei */
X
X/* file stuff for input/output files */
X
Xstruct infiledata pi_file = { NULL, -1 }; /* input files */
Xstruct infiledata si_file = { NULL, -1 };
Xstruct infiledata *infile = &pi_file; /* pointer to currently active input file structure */
Xstruct outfiledata po_file, so_file; /* output files */
Xstruct outfiledata *outfile = &po_file; /* pointer to currently active output file structure */
XFILE *eisw; /* indirect command file pointer */
X
X/* process E commands */
X
Xdo_e()
X {
X char c; /* temps */
X int old_var;
X FILE *t_eisw;
X
X switch (mapch_l[getcmdc(trace_sw)]) /* read next character and dispatch */
X {
X
X/* numeric values */
X
X case 'd': /* ED */
X set_var(&ed_val);
X break;
X
X case 's': /* ES */
X set_var(&es_val);
X break;
X
X case 't': /* ET */
X old_var = et_val;
X set_var(&et_val);
X et_val = (et_val & 0100651) | 001006; /* force read_only bits */
X if ((et_val ^ old_var) & ET_TRUNC) window(WIN_REDRAW); /* redraw if ET & 256 changes */
X break;
X
X case 'u': /* EU */
X set_var(&eu_val);
X break;
X
X case 'v': /* EV */
X set_var(&ev_val);
X break;
X
X case 'z': /* EZ */
X old_var = ez_val;
X set_var(&ez_val);
X tabmask = (ez_val & EZ_TAB4) ? 3 : 7; /* set tab mask */
X if ((ez_val ^ old_var) & EZ_TAB4) window(WIN_REDRAW); /* force window redisplay if EZ_TAB4 changes */
X break;
X/* E_ search */
X
X case '_':
X do_nsearch('e');
X break;
X
X/* file I/O commands */
X
X case 'a': /* set secondary output */
X outfile = &so_file;
X break;
X
X case 'b': /* open read/write with backup */
X if (!read_filename(1, 'r')) ERROR(E_NFI); /* read the name */
X if (infile->fd) fclose(infile->fd); /* close previously-open file */
X if (!(infile->fd = fopen(fbuf.f->ch, "r")))
X {
X if (!colonflag) ERROR(E_FNF);
X }
X else
X {
X if (outfile->fd) ERROR(E_OFO); /* output file already open */
X for (ll = 0; ll < CELLSIZE; ll++) /* save file string */
X if ((outfile->t_name[ll] = outfile->f_name[ll] = fbuf.f->ch[ll]) == '\0') break;
X outfile->name_size = ll;
X outfile->t_name[ll++] = '.';
X outfile->t_name[ll++] = 't';
X outfile->t_name[ll++] = 'm';
X outfile->t_name[ll++] = 'p';
X outfile->t_name[ll] = '\0';
X if (!(outfile->fd = fopen(outfile->t_name, "w"))) ERROR(E_COF);
X outfile->bak = 1; /* set backup mode */
X }
X infile->eofsw = -1 - (esp->val1 = (infile->fd) ? -1 : 0);
X esp->flag1 = colonflag;
X colonflag = 0;
X break;
X
X case 'x': /* finish edit and exit */
X exitflag = -1;
X
X /* --- fall through to "EC" --- */
X
X case 'c': /* finish edit */
X set_pointer(0, &aa); /* set a pointer to start of text buffer */
X write_file(&aa, z, ctrl_e); /* write the current buffer */
X dot = z = 0; /* empty the buffer */
X window(WIN_REDRAW); /* force window redraw */
X if ((outfile->fd) && (infile->fd) && !(infile->eofsw)) /* if any input remaining, copy it to output */
X while ((c = getc(infile->fd)) != EOF) putc(c, outfile->fd);
X
X /* --- fall through to "EF" --- */
X case 'f': /* close output file */
X if (outfile->fd) /* only if one is open */
X {
X fclose(outfile->fd);
X if (outfile->bak & 1) /* if this is "backup" mode */
X {
X outfile->f_name[outfile->name_size] = '.';
X outfile->f_name[outfile->name_size+1] = 'b';
X outfile->f_name[outfile->name_size+2] = 'a';
X outfile->f_name[outfile->name_size+3] = 'k';
X outfile->f_name[outfile->name_size+4] = '\0';
X outfile->t_name[outfile->name_size] = '\0';
X rename(outfile->t_name, outfile->f_name); /* rename orig file */
X }
X
X if (!(outfile->bak & 8)) /* if output file had ".tmp" extension */
X { /* remove it */
X outfile->t_name[outfile->name_size] = '.';
X outfile->f_name[outfile->name_size] = '\0';
X rename(outfile->t_name, outfile->f_name); /* rename output */
X }
X }
X outfile->fd = NULL; /* mark "no output file open" */
X break;
X
X case 'i': /* indirect file execution */
X if (!read_filename(1, 'i')) /* if no filename specified, reset command input */
X {
X if (eisw) /* if ending a file execute, restore the previous "old command string" */
X {
X fclose(eisw); /* return the file descriptor */
X dly_free_blist(cbuf.f); /* return the command string used by the file (after execution done) */
X cbuf.f = oldcstring.f;
X cbuf.z = oldcstring.z;
X }
X t_eisw = 0;
X }
X else if (!(t_eisw = fopen(fbuf.f->ch, "r")))
X {
X if (!colonflag) ERROR(E_FNF);
X }
X else if (!eisw) /* if this "ei" came from the command string */
X {
X oldcstring.f = cbuf.f; /* save current command string */
X oldcstring.z = cbuf.z;
X cbuf.f = NULL; /* and make it inaccessible to "rdcmd" */
X }
X if (eisw) fclose(eisw); /* if a command file had been open, close it */
X esp->val1 = (eisw = t_eisw) ? -1 : 0;
X esp->flag1 = colonflag;
X colonflag = 0;
X esp->op = OP_START;
X break;
X case 'k': /* kill output file */
X kill_output(outfile);
X break;
X
X case 'p': /* switch to secondary input */
X infile = &si_file;
X break;
X
X case 'r': /* specify input file, or switch to primary input */
X if (!read_filename(0, 'r')) infile = &pi_file; /* no name, switch to primary input */
X else
X {
X if (infile->fd) fclose(infile->fd); /* close previously-open file */
X if (!(infile->fd = fopen(fbuf.f->ch, "r")))
X {
X if (!colonflag) ERROR(E_FNF);
X }
X }
X infile->eofsw = -1 - (esp->val1 = (infile->fd) ? -1 : 0);
X esp->flag1 = colonflag;
X colonflag = 0;
X esp->op = OP_START;
X break;
X
X case 'w': /* specify output file, or switch to primary output */
X if(!read_filename(0, 'w')) outfile = &po_file;
X else
X {
X if (outfile->fd) ERROR(E_OFO); /* output file already open */
X for (ll = 0; ll < CELLSIZE; ll++) /* save file string */
X if ((outfile->t_name[ll] = outfile->f_name[ll] = fbuf.f->ch[ll]) == '\0') break;
X outfile->name_size = ll;
X if (!(ez_val & EZ_NOTMPFIL)) /* if not using literal output name */
X {
X outfile->t_name[ll++] = '.'; /* use provisional suffix ".tmp" */
X outfile->t_name[ll++] = 't';
X outfile->t_name[ll++] = 'm';
X outfile->t_name[ll++] = 'p';
X outfile->t_name[ll] = '\0';
X }
X if (!(outfile->fd = fopen(outfile->t_name, "w"))) ERROR(E_COF);
X outfile->bak = ez_val & EZ_NOTMPFIL; /* save "temp suffix" status */
X }
X break;
X
X case 'y': /* EY is Y without protection */
X if (esp->flag1) ERROR(E_NYA);
X dot = z = 0; /* clear buffer */
X set_pointer(0, &aa);
X read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) );
X esp->flag1 = colonflag;
X colonflag = 0;
X esp->op = OP_START;
X break;
X case 'n': /* wildcard filespec */
X esp->val1 = do_en();
X esp->flag1 = colonflag;
X colonflag = 0;
X esp->op = OP_START;
X break;
X
X case 'q': /* system command */
X esp->val1 = do_eq(); /* do this as a separate routine */
X esp->flag1 = colonflag;
X colonflag = 0;
X esp->op = OP_START;
X break;
X
X default:
X ERROR(E_IEC);
X }
X }
X/* routine to execute a system command */
X/* this is done by forking off another process */
X/* to execute a shell via 'execl' */
X/* routine returns -1 if success, 0 if error in fork */
X
Xint do_eq()
X {
X int t;
X union wait status;
X char *pname; /* pointer to name of shell */
X extern char *getenv();
X
X build_string(&sysbuf);
X if (sysbuf.z > CELLSIZE-2) ERROR(E_STL); /* command must fit within one cell */
X sysbuf.f->ch[sysbuf.z] = '\0'; /* store terminating null */
X if (!(pname = getenv("SHELL"))) ERROR(E_SYS); /* read shell name */
X
X if (!esp->flag1) /* if not m,nEQ command */
X {
X if (win_data[7]) window(WIN_SUSP); /* restore full screen */
X crlf(); /* force characters out */
X setup_tty(TTY_SUSP); /* restore terminal to normal mode */
X
X t = vfork(); /* fork a new process */
X if (t == 0) /* if this is the child */
X {
X execl(pname, pname, "-c", &sysbuf.f->ch[0], 0); /* call the named Unix routine */
X printf("Error in 'execl'\n"); /* normally shouldn't get here */
X exit(1);
X }
X
X while (wait(&status) != t); /* if parent, wait for child to finish */
X if (status.w_retcode) t = -1; /* keep failure indication from child */
X
X setup_tty(TTY_RESUME); /* restore terminal to teco mode */
X if (win_data[7]) /* if window was enabled */
X {
X vt(VT_SETSPEC1); /* set reverse video */
X fputs("Type RETURN to continue", stdout); /* require CR before continuing */
X vt(VT_CLRSPEC); /* reverse video off */
X while (gettty() != LF);
X putchar(CR); /* back to beginning of line */
X vt(VT_EEOL); /* and erase the message */
X window(WIN_RESUME); /* re-enable window */
X window(WIN_REDRAW); /* and make it redraw afterwards */
X }
X }
X
X else t = do_eq1(pname); /* m,nEQ command */
X
X return( (t == -1) ? 0 : -1); /* return failure if fork failed or proc status nonzero */
X }
X/* Execute m,nEQtext$ command. Run "text" as a Unix command that */
X/* receives its std input from chars m through n of teco's buffer. */
X/* Output from the command is placed in Q#. */
X
Xint do_eq1(shell)
X char *shell; /* arg is pointer to shell name */
X {
X int ff, pipe_in[2], pipe_out[2]; /* fork result and two pipes */
X FILE *xx_in, *xx_out; /* std in and out for called process */
X FILE *fdopen();
X union wait status;
X
X ll = line_args(1, &aa); /* set aa to start of text, ll to number of chars */
X dot += ll; /* set pointer at end of text */
X ctrl_s = -ll; /* set ^S to - # of chars */
X
X if (pipe(pipe_out)) ERROR(E_SYS); /* make input pipe; failure if can't */
X
X if (win_data[7]) window(WIN_SUSP); /* disable split screen */
X setup_tty(TTY_SUSP); /* put console back to original state */
X if ((ff = fork()) == -1) /* fork first child: if error, quit */
X {
X close(pipe_out[0]);
X close(pipe_out[1]);
X setup_tty(TTY_RESUME);
X if (win_data[7]) window(WIN_RESUME), window(WIN_REDRAW);
X ERROR(E_SYS);
X }
X
X if (ff) /* if this is the parent, the task is to read into q# */
X {
X make_buffer(&timbuf); /* initialize the q# header */
X bb.p = timbuf.f; /* init bb to point to q# */
X timbuf.z = bb.c = 0;
X
X close(pipe_out[1]); /* parent won't write to this pipe */
X
X if ((xx_out = fdopen(pipe_out[0], "r")) == 0) /* open the "std out" pipe for reading */
X {
X close(pipe_out[0]); /* if can't open output pipe */
X setup_tty(TTY_RESUME);
X if (win_data[7]) window(WIN_RESUME), window(WIN_REDRAW);
X ERROR(E_SYS); /* "open" failure */
X }
X read_stream(xx_out, 0, &bb, &timbuf.z, 0, 0, 1); /* read from pipe to q# */
X close(pipe_out[0]);
X
X while (wait(&status) != ff); /* wait for children to finish */
X setup_tty(TTY_RESUME);
X if (win_data[7]) window(WIN_RESUME), window(WIN_REDRAW);
X return(status.w_retcode ? -1 : 0);
X }
X/* This is the child. It in turn forks into two processes, of which the "parent" */
X/* (original child) writes the specified part of the buffer to the pipe, and the */
X/* new child (grandchild to the original teco) execl's the Unix command. */
X
X else /* this is the child */
X {
X close(pipe_out[0]); /* won't read from "output" pipe */
X if (pipe(pipe_in)) exit(1); /* make the "std in" pipe for the process, quit if can't */
X
X if ((ff = fork()) == -1) exit(1); /* fork to two processes (total 3), exit if error */
X
X if (ff) /* parent - will send chars */
X {
X close(pipe_in[0]); /* won't read from this pipe */
X
X /* open pipe for writing; exit if open fails */
X
X if ((xx_in = fdopen(pipe_in[1], "w")) == 0) exit(1);
X
X write_stream(xx_in, &aa, ll, 0); /* write to stream, CRLF becomes LF */
X fclose(xx_in);
X
X while (wait(&status) != ff); /* wait for child */
X exit(status.w_retcode); /* exit with child's status */
X }
X
X else /* this process is the grandchild */
X {
X close(pipe_in[1]); /* close "input" for writing */
X dup2(pipe_in[0], fileno(stdin)); /* substitute pipe_in for stdin */
X dup2(pipe_out[1], fileno(stdout)); /* and pipe_out for stdout */
X close(pipe_in[0]); /* close original descriptors */
X close(pipe_out[1]);
X
X execl(shell, shell, "-c", &sysbuf.f->ch[0], 0); /* execute specified routine */
X fputs("execl failed\n", stderr);
X exit(1);
X }
X }
X }
X/* Routines to handle EN wild-card file specification */
X/* ENfilespec$ defines file class, leaving 'filespec' */
X/* in filespec buffer and reading expanded list of */
X/* files into local buffer. EN$ gets next filespec */
X/* into filespec buffer. */
X
Xstruct qh en_buf; /* header for storage for file list */
Xstruct qp en_ptr; /* pointer to load/read file list */
Xstatic char glob_cmd0[] = { 'g', 'l', 'o', 'b', ' ' } ;
X
Xint do_en()
X {
X int t;
X
X if (build_string(&fbuf)) /* if a file string is specified */
X {
X if (fbuf.z > CELLSIZE-2) ERROR(E_STL); /* upper limit on string length */
X fbuf.f->ch[fbuf.z] = '\0'; /* terminating null */
X t = do_glob(&en_buf); /* glob the result */
X en_ptr.p = en_buf.f; /* set the buffer pointer to the beginning of the buffer */
X en_ptr.dot = en_ptr.c = 0;
X }
X else /* if no string, get next filename */
X {
X do_en_next();
X t = (fbuf.z) ? -1 : 0; /* t zero if no more filespecs */
X if (!t && !colonflag) ERROR(E_NFI); /* if no colon, end of spec is an error */
X }
X return (t);
X }
X
X/* routine to expand the string in the filespec buffer */
X/* argument is the address of a qh that gets the expanded string */
X/* argument->v gets set to the number of file specs found */
X
Xint do_glob(buff)
X struct qh *buff;
X {
X char glob_cmd[CELLSIZE+5]; /* "glob filespec" command string */
X int t;
X char c;
X int glob_pipe[2]; /* pipe to forked shell for expanding filenames */
X struct qp glob_ptr; /* pointer for loading result buffer */
X FILE *xx_out; /* stream for reading chars from pipe */
X FILE *fdopen();
X union wait status;
X
X make_buffer(buff); /* initialize expanded file buffer */
X glob_ptr.p = buff->f; /* initialize pointer to buffer */
X glob_ptr.c = glob_ptr.dot = buff->z = buff->v = 0;
X for (t = 0; t < 5; t++) glob_cmd[t] = glob_cmd0[t]; /* set up "glob filespec" command */
X for (t = 0; t < fbuf.z +1; t++) glob_cmd[t+5] = fbuf.f->ch[t];
X
X if (pipe(glob_pipe)) ERROR(E_SYS); /* make a pipe */
X setup_tty(TTY_SUSP); /* put console back to normal */
X if ((t = fork()) == -1) /* spawn a child... if failure */
X {
X close(glob_pipe[0]); /* undo the pipe */
X close(glob_pipe[1]);
X setup_tty(TTY_RESUME);
X ERROR(E_SYS); /* and exit with failure */
X }
X
X if (t) /* if this is the parent */
X {
X close(glob_pipe[1]); /* parent won't write */
X if ((xx_out = fdopen(glob_pipe[0], "r")) == 0) /* open pipe for read */
X {
X close(glob_pipe[0]); /* failure to open */
X setup_tty(TTY_RESUME);
X ERROR(E_SYS);
X }
X
X while ((c = getc(xx_out)) != EOF) /* read characters from pipe */
X {
X if (c == '\0') ++buff->v; /* count null chars that separate file specs */
X glob_ptr.p->ch[glob_ptr.c] = c; /* store them in buffer */
X fwdcx(&glob_ptr);
X }
X
X fclose(xx_out); /* through with stream */
X buff->z = glob_ptr.dot; /* save character count */
X while (wait(&status) != t); /* wait for child to finish */
X setup_tty(TTY_RESUME);
X return(status.w_retcode ? 0 : -1); /* return success unless child exited nonzero */
X }
X else /* this is the child */
X {
X close(glob_pipe[0]); /* child won't read */
X dup2(glob_pipe[1], fileno(stdout)); /* substitute pipe for standard out */
X close(glob_pipe[1]); /* don't need that anymore */
X execl("/bin/csh", "csh", "-fc", glob_cmd, 0); /* execute the "glob" */
X fputs("execl failed\n", stderr);
X exit(1);
X }
X }
X
X/* routine to get next file spec from "EN" list into filespec buffer */
X
Xdo_en_next()
X {
X char c;
X
X make_buffer(&fbuf); /* initialize the filespec buffer */
X fbuf.z = 0;
X
X while(en_ptr.dot < en_buf.z) /* stop at end of string */
X {
X c = en_ptr.p->ch[en_ptr.c];
X fwdc(&en_ptr);
X if (!c) break; /* null is terminator between file specs */
X fbuf.f->ch[fbuf.z++] = c; /* store char */
X if (fbuf.z >= CELLSIZE-1) ERROR(E_STL); /* limit on filespec size */
X }
X
X fbuf.f->ch[fbuf.z] = '\0'; /* filespec ends with NULL */
X }
X
X/* routine to read a file name */
X/* reads it into fbuf text area */
X/* returns nonzero if a name, 0 if none */
X/* flag nonzero => empty name clears filespec buffer */
X/* func is 'r' for ER or EB cmds, 'i' for EI, 'w' for EW */
X
Xint read_filename(flag, func)
X int flag;
X char func;
X {
X int i, t, expand;
X char c;
X struct qh temp_buff; /* temp buffer for globbing filespec */
X
X if (!(t = build_string(&fbuf))) /* if no name spec'd */
X {
X if (flag) fbuf.z = 0; /* if no name spec'd, set length to 0 */
X }
X else
X {
X if (fbuf.z > CELLSIZE-2) ERROR(E_STL);
X fbuf.f->ch[fbuf.z] = '\0'; /* store terminating NULL */
X
X/* check for characters to be expanded by the shell */
X
X for (i = 0; i < fbuf.z; i++)
X if ((c = fbuf.f->ch[i]) == '*' || c == '?' || c == '[' || c == 0173) break;
X if ( (expand = (i < fbuf.z)) || fbuf.f->ch[0] == '~') /* one of these was found, or first char is ~ */
X {
X temp_buff.f = NULL; /* make a temp buffer to glob filename into */
X make_buffer(temp_buff);
X do_glob(&temp_buff); /* expand the file name */
X if (temp_buff.z == 0) /* no match */
X {
X free_blist(temp_buff.f); /* return the storage */
X ERROR(func == 'w' ? E_COF : E_FNF); /* "can't open" or "file not found" */
X }
X else if (temp_buff.v == 0) /* if exactly one file name */
X {
X free_blist(fbuf.f); /* return the old file spec */
X fbuf.f = temp_buff.f; /* put the temp buffer there instead */
X fbuf.z = temp_buff.z;
X if (fbuf.z > CELLSIZE-2) ERROR(E_STL);
X fbuf.f->ch[fbuf.z] = '\0';
X
X if (func == 'w' && expand) /* if this is EW and 'twas from a wildcard expansion */
X {
X vt(VT_SETSPEC1); /* "file XXXX already exists: overwrite? [yn]" */
X fputs("File ", stdout);
X fputs(fbuf.f->ch, stdout);
X fputs(" already exists: overwrite? [ny] ", stdout);
X vt(VT_CLRSPEC);
X c = gettty(); /* read user's response */
X putchar(CR);
X vt(VT_EEOL); /* clean up the screen */
X if (c != 'y') ERROR(E_COF); /* abort here */
X }
X }
X
X else /* multiple file specs */
X {
X if (func != 'r' || !(ez_val & EZ_MULT)) /* if multiple file specs here aren't allowed */
X {
X free_blist(temp_buff.f); /* return the storage */
X ERROR(E_AMB);
X }
X free_blist(en_buf.f); /* substitute the expansion for the "EN" list */
X en_ptr.p = en_buf.f = temp_buff.f; /* and initialize the "EN" list pointer */
X en_buf.z = temp_buff.z;
X en_ptr.dot = en_ptr.c = 0;
X do_en_next(); /* get the first file */
X }
X }
X }
X return(t);
X }
X
X
X
X/* fetch or set variable */
X
Xset_var(arg)
X int *arg; /* argument is pointer to variable */
X {
X if (esp->flag1) /* if an argument, then set the variable */
X {
X if (esp->flag2) /* if two arguments, then <clr>, <set> */
X *arg = (*arg & ~esp->val2) | esp->val1;
X else *arg = esp->val1; /* one arg is new value */
X esp->flag2 = esp->flag1 = 0; /* consume argument */
X }
X else /* otherwise fetch the variable's value */
X {
X esp->val1 = *arg;
X esp->flag1 = 1;
X }
X }
X
X
X
X/* read from selected input file stream into specified buffer */
X/* terminate on end-of-file or form feed */
X/* if endsw > 0 terminates after that many lines */
X/* if endsw < 0 stops if z > BUFF_LIMIT */
X/* returns -1 if read EOF, 0 otherwise */
X
Xint read_file(buff, nchars, endsw)
X struct qp *buff;
X int *nchars, endsw;
X {
X if (!infile->fd) infile->eofsw = -1, ctrl_e = 0; /* return if no input file open */
X else infile->eofsw = read_stream(infile->fd, &ctrl_e, buff, nchars, endsw, ez_val & EZ_CRLF, ez_val & EZ_READFF);
X return(esp->val1 = infile->eofsw);
X }
X/* read from an I/O stream into specified buffer */
X/* this is used by read_file and by "eq" pipe from other Unix processes */
X/* args buff, nchars, endsw as above; file is stream pointer, ff_found is */
X/* address of a switch to set if read ended with a FF, crlf_sw is lf->crlf */
X/* conversion, ff_sw indicates whether to stop on a form feed. */
X
Xint read_stream(file, ff_found, buff, nchars, endsw, crlf_sw, ff_sw)
X FILE *file;
X struct qp *buff;
X int *ff_found, *nchars, endsw, crlf_sw, ff_sw;
X {
X char chr;
X int crflag;
X register struct buffcell *p;
X register int c;
X
X p = (*buff).p; /* copy pointer locally */
X c = (*buff).c;
X crflag = 0; /* "last char wasn't CR" */
X while (((chr = getc(file)) != EOF) && ((chr != FF) || ff_sw))
X {
X if ((chr == LF) && !crflag && !crlf_sw) /* automatic cr before lf */
X {
X p->ch[c] = CR; /* store a cr */
X ++(*nchars); /* increment buffer count */
X if (++c > CELLSIZE-1) /* next cell? */
X {
X if (!p->f) /* need a new cell? */
X {
X p->f = get_bcell();
X p->f->b = p;
X }
X p = p->f;
X c = 0;
X }
X }
X p->ch[c] = chr; /* store char */
X ++(*nchars); /* increment character count */
X if (++c > CELLSIZE-1) /* next cell? */
X {
X if (!p->f) /* need a new cell? */
X {
X p->f = get_bcell();
X p->f->b = p;
X }
X p = p->f;
X c = 0;
X }
X crflag = (chr == CR); /* flag set if last char was CR */
X if ((chr == LF) && ((endsw < 0 && z > BUFF_LIMIT) || (endsw > 0 && --endsw == 0))) break; /* term after N lines */
X }
X (*buff).p = p; /* update pointer */
X (*buff).c = c;
X if (ff_found) *ff_found = (chr == FF) ? -1 : 0; /* set flag to indicate whether FF found */
X return( (chr == EOF) ? -1 : 0); /* and return "eof found" value */
X }
X/* routine to write text buffer out to selected output file */
X/* arguments are qp to start of text, number of characters, */
X/* and an "append FF" switch */
X
Xwrite_file(buff, nchars, ffsw)
X struct qp *buff;
X int nchars, ffsw;
X {
X if (!outfile->fd && (nchars)) ERROR(E_NFO);
X else write_stream(outfile->fd, buff, nchars, ez_val & EZ_CRLF);
X if (outfile->fd && ffsw) putc(FF, outfile->fd);
X }
X
X
X/* routine to write text buffer to I/O stream. Used by */
X/* write_file, above, and by "eq" write to pipe to other */
X/* Unix processes. Arguments buff, nchars as above; file */
X/* is stream pointer, crlf_sw zero converts CRLF to LF */
X
Xwrite_stream(file, buff, nchars, crlf_sw)
X FILE *file;
X struct qp *buff;
X int nchars, crlf_sw;
X {
X char c;
X int crflag;
X
X crflag = 0;
X for (; nchars > 0; nchars--)
X {
X if ((c = (*buff).p->ch[(*buff).c]) == CR) crflag = 1; /* set flag if a c.r. */
X else
X {
X if ((crflag) && ((c != LF) || crlf_sw)) /* if c.r. not before lf, or if not in */
X putc(CR, file); /* "no cr" mode, output the c.r. */
X crflag = 0;
X putc(c, file);
X }
X if (++(*buff).c > CELLSIZE-1)
X {
X (*buff).p = (*buff).p->f;
X (*buff).c = 0;
X }
X }
X }
X
X
X/* routine to kill output file: argument is pointer to an output file structure */
X
Xkill_output(outptr)
X struct outfiledata *outptr;
X {
X if (outptr->fd)
X {
X fclose(outptr->fd);
X unlink(outptr->t_name);
X outptr->fd = NULL;
X }
X }
X/* "panic" routine called when "hangup" signal occurs */
X/* this routine saves the text buffer and closes the output files */
X
Xchar panic_name[] = "TECO_SAVED.tmp"; /* name of file created to save buffer */
X
Xpanic()
X {
X if (!outfile->fd && z) outfile->fd = fopen(panic_name, "w"); /* if buffer nonempty and no file open, make one */
X
X set_pointer(0, &aa); /* set a pointer to start of text buffer */
X if (outfile->fd && z) write_file(&aa, z, 0); /* and write out buffer unless "open" failed */
X
X if (po_file.fd) fclose(po_file.fd), po_file.fd = NULL; /* close any open output files */
X if (so_file.fd) fclose(so_file.fd), so_file.fd = NULL;
X }
X/* do "F" commands */
X
Xdo_f()
X {
X struct buffcell *delete_p;
X
X switch (mapch_l[getcmdc(trace_sw)]) /* read next character and dispatch */
X {
X case '<': /* back to beginning of current iteration */
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); /* else, restart current macro */
X break;
X
X case '>': /* to end of current iteration */
X find_enditer(); /* find it */
X if ( ( ((esp->flag1) ? esp->val1 : srch_result) >= 0) ? (~colonflag) : colonflag) /* if exit */
X pop_iteration(0); /* and exit if appropriate */
X break;
X
X case '\'': /* to end of conditional */
X case '|': /* to "else," or end */
X find_endcond(cmdc);
X break;
X
X/* "F" search commands */
X
X case 'b': /* bounded search, alternative args */
X do_fb();
X break;
X
X case 'c': /* bounded search, alternative args, then "FR" */
X if (do_fb()) goto do_fr;
X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
X break;
X
X case 'n': /* do "N" and then "FR" */
X if (do_nsearch('n')) goto do_fr;
X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
X break;
X
X case '_': /* do "_" and then "FR" */
X if (do_nsearch('_')) goto do_fr;
X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
X break;
X
X case 's': /* search and replace: search, then do "FR" */
X build_string(&sbuf); /* read search string and terminator */
X if (end_search( do_search( setup_search() ) )) goto do_fr; /* if search passed, do "FR" */
X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
X break;
X case 'r': /* replace last insert, search, etc. */
X if (esp->flag1) ERROR(E_NFR); /* shouldn't have argument */
X term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */
X atflag = 0;
X do_fr: /* entry from FN, F_, and FC */
X set_pointer(dot, &cc); /* save a pointer to the current spot */
X dot += ctrl_s; /* back dot up over the string */
X set_pointer(dot, &aa); /* code from "insert1": convert dot to a qp */
X delete_p = aa.p; /* save beginning of original cell */
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 ins_count = aa.c; /* save char position of dot in cell */
X aa.c = 0;
X
X movenchars(&aa, &bb, ins_count); /* copy cell up to dot */
X moveuntil(&cptr, &bb, term_char, &ins_count, cptr.z-cptr.dot, trace_sw); /* insert */
X cptr.dot += ins_count; /* advance command-string pointer */
X getcmdc(trace_sw); /* skip terminator */
X
X z += ctrl_s; /* subtract delete length from buffer count */
X delete_p->b->f = insert_p; /* put the new cell where the old one was */
X insert_p->b = delete_p->b; /* code borrowed from "insert2" */
X insert_p = NULL;
X
X if (bb.c == cc.c) /* if replacement text was same length, we can save time */
X {
X for (; bb.c < CELLSIZE; bb.c++) bb.p->ch[bb.c] = cc.p->ch[bb.c]; /* copy rest of cell */
X bb.p->f = cc.p->f; /* replace orig cell's place in chain with end of new list */
X if (bb.p->f) bb.p->f->b = bb.p;
X cc.p->f = NULL; /* terminate the part snipped out */
X free_blist(delete_p); /* return the old part */
X }
X
X else /* different positions: shift the remainder of the buffer */
X {
X bb.p->f = delete_p; /* splice rest of buffer to end */
X delete_p->b = bb.p;
X movenchars(&cc, &bb, z-dot); /* squeeze buffer */
X free_blist(bb.p->f); /* return unused cells */
X bb.p->f = NULL; /* and end the buffer */
X }
X
X z += ins_count; /* add # of chars inserted */
X dot += ins_count;
X ctrl_s = -ins_count; /* save string length */
X esp->flag1 = esp->flag2 = 0; /* and consume arguments */
X esp->op = OP_START;
X break;
X
X default:
X ERROR(E_IFC);
X }
X }
X/* routines for macro iteration */
X/* pop iteration: if arg nonzero, exit unconditionally */
X/* else check exit conditions and exit or reiterate */
X
Xpop_iteration(arg)
X int arg;
X {
X if (!arg && (!cptr.il->dflag || (--(cptr.il->count) > 0)) ) /* if reiteration */
X {
X cptr.p = cptr.il->p; /* restore */
X cptr.c = cptr.il->c;
X cptr.dot = cptr.il->dot;
X }
X else
X {
X if (cptr.il->b) cptr.il = cptr.il->b; /* if not last thing on stack, back up */
X else cptr.flag &= ~F_ITER; /* else clear "iteration" flag */
X }
X }
X
X
X/* find end of iteration - read over arbitrary <> and one > */
X
Xfind_enditer()
X {
X register int icnt;
X
X for (icnt = 1; icnt > 0;) /* scan for matching > */
X {
X while ((skipto(0) != '<') && (skipc != '>')); /* scan for next < or > */
X if (skipc == '<') ++icnt; /* and keep track of macro level */
X else --icnt;
X }
X }
X
X
X
X/* find end of conditional */
Xchar find_endcond(arg)
X char arg;
X {
X register int icnt;
X
X for (icnt = 1; icnt > 0;)
X {
X while ((skipto(0) != '"') && (skipc != '\'') && (skipc != '|'));
X if (skipc == '"') ++icnt;
X else if (skipc == '\'') -- icnt;
X else if ((icnt == 1) && (arg == '|')) break;
X }
X }
X
END_OF_te_exec2.c
if test 29256 -ne `wc -c <te_exec2.c`; then
echo shar: \"te_exec2.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
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