|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 21012 (0x5214) Types: TextFile Names: »te_exec1.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/euug-87hel/sec1/teco/te_exec1.c«
/* TECO for Ultrix Copyright 1986 Matt Fichtenbaum */ /* This program and its components belong to GenRad Inc, Concord MA 01742 */ /* They may be copied if this copyright notice is included */ /* te_exec1.c continue executing commands 1/8/87 */ #include "te_defs.h" exec_cmds1() { char command; /* command character */ int cond; /* conditional in progress */ switch (command = mapch_l[cmdc]) { /* operators */ case '+': esp->exp = (esp->flag1) ? esp->val1 : 0; esp->flag1 = 0; esp->op = OP_ADD; break; case '-': esp->exp = (esp->flag1) ? esp->val1 : 0; esp->flag1 = 0; esp->op = OP_SUB; break; case '*': esp->exp = (esp->flag1) ? esp->val1 : 0; esp->flag1 = 0; esp->op = OP_MULT; break; case '/': esp->exp = (esp->flag1) ? esp->val1 : 0; esp->flag1 = 0; esp->op = OP_DIV; break; case '&': esp->exp = (esp->flag1) ? esp->val1 : 0; esp->flag1 = 0; esp->op = OP_AND; break; case '#': esp->exp = (esp->flag1) ? esp->val1 : 0; esp->flag1 = 0; esp->op = OP_OR; break; case ')': if ((!esp->flag1) || (esp <= &estack[0])) ERROR(E_NAP); --esp; esp->val1 = (esp+1)->val1; /* carry value from inside () */ esp->flag1 = 1; break; \f case ',': if (!esp->flag1) ERROR(E_NAC); else esp->val2 = esp->val1; esp->flag2 = 1; esp->flag1 = 0; break; case CTL (_): if (!esp->flag1) ERROR(E_NAB); else esp->val1 = ~esp->val1; break; /* radix control */ case CTL (D): ctrl_r = 10; esp->flag1 = 0; esp->op = OP_START; break; case CTL (O): ctrl_r = 8; esp->flag1 = 0; esp->op = OP_START; break; case CTL (R): if (!esp->flag1) /* fetch it */ { esp->val1 = ctrl_r; esp->flag1 = 1; } else { if ((esp->val1 != 8) && (esp->val1 != 10) && (esp->val1 != 16)) ERROR(E_IRA); ctrl_r = esp->val1; esp->flag1 = 0; esp->op = OP_START; } break; /* other commands */ case CTL (C): /* 1 ^C stops macro execution, 2 exit */ if (peekcmdc(CTL (C))) exitflag = -1; /* 2 ^C: stop execution and exit */ else if (msp <= &mstack[0]) exitflag = 1; /* 1 ^C: in command string: stop execution */ else --msp; /* in a macro - pop it */ break; case CTL (X): /* search mode flag */ set_var(&ctrl_x); break; case 'e': do_e(); break; case 'f': do_f(); break; \f /* macro call, iteration, conditional */ case 'm': /* macro call */ mm = getqspec(0, getcmdc(trace_sw)); /* read the macro name */ if (msp > &mstack[MSTACKSIZE-1]) ERROR(E_PDO); /* check room for another level */ ++msp; /* push stack */ cptr.p = qreg[mm].f; /* to stack entry, put q-reg text start */ cptr.flag = cptr.c = cptr.dot = 0; /* initial char position, iteration flag */ cptr.z = qreg[mm].z; /* number of chars in macro */ break; case '<': /* begin iteration */ if ((esp->flag1) && (esp->val1 <= 0)) /* if this is not to be executed */ find_enditer(); /* just skip the intervening stuff */ else { if (!cptr.il) /* does this macro have an iteration list? */ { cptr.il = (struct is *) get_dcell(); /* no, make one for it */ cptr.il->b = NULL; /* with NULL reverse pointer */ } else if (cptr.flag & F_ITER) /* is there an iteration in process? */ { if (!cptr.il->f) /* yes, if it has no forward pointer */ { cptr.il->f = (struct is *) get_dcell(); /* append a cell to the iteration list */ cptr.il->f->b = cptr.il; /* and link it in */ } cptr.il = cptr.il->f; /* and advance the iteration list pointer to it */ } cptr.flag |= F_ITER; /* set iteration flag */ cptr.il->p = cptr.p; /* save start of iteration */ cptr.il->c = cptr.c; cptr.il->dot = cptr.dot; if (cptr.il->dflag = esp->flag1) /* if there is an argument, set the "def iter" flag */ { cptr.il->count = esp->val1; /* save the count */ esp->flag1 = 0; /* and consume the arg */ } } break; case '>': /* end iteration */ if (!(cptr.flag & F_ITER)) ERROR(E_BNI); /* error if > not in iteration */ pop_iteration(0); /* decrement count and pop conditionally */ esp->flag1 = esp->flag2 = 0; /* consume arguments */ esp->op = OP_START; break; case ';': /* semicolon iteration exit */ if (!(cptr.flag &F_ITER)) ERROR(E_SNI); /* error if ; not in iteration */ if ( ( ((esp->flag1) ? esp->val1 : srch_result) >= 0) ? (!colonflag) : colonflag) /* if exit */ { find_enditer(); /* get to end of iteration */ pop_iteration(1); /* and pop unconditionally */ } esp->flag1 = colonflag = 0; /* consume arg and colon */ esp->op = OP_START; break; \f /* conditionals */ case '"': if (!esp->flag1) ERROR(E_NAQ); /* must be an argument */ esp->flag1 = 0; /* consume argument */ esp->op = OP_START; switch (mapch_l[getcmdc(trace_sw)]) { case 'a': cond = isalpha(esp->val1); break; case 'c': cond = isalpha(esp->val1) | (esp->val1 == '$') | (esp->val1 == '.'); break; case 'd': cond = isdigit(esp->val1); break; case 'e': case 'f': case 'u': case '=': cond = !(esp->val1); break; case 'g': case '>': cond = (esp->val1 > 0); break; case 'l': case 's': case 't': case '<': cond = (esp->val1 < 0); break; case 'n': cond = esp->val1; break; case 'r': cond = isalnum(esp->val1); break; case 'v': cond = islower(esp->val1); break; case 'w': cond = isupper(esp->val1); break; default: ERROR(E_IQC); } \f if (!cond) /* if this conditional isn't satisfied */ { for (ll = 1; ll > 0;) /* read to matching | or ' */ { while ((skipto(0) != '"') && (skipc != '|') && (skipc != '\'')); /* skip chars */ if (skipc == '"') ++ll; /* start another level */ else if (skipc == '\'') --ll; /* end a level */ else if (ll == 1) break; /* "else" (|): if on this level, start executing */ } } break; case '\'': /* end of conditional */ break; /* ignore it if executing */ case '|': /* "else" clause */ for (ll = 1; ll > 0;) /* skip to matching ' */ { while ((skipto(0) != '"') && (skipc != '\'')); /* skip chars */ if (skipc == '"') ++ll; /* start another level */ else --ll; /* end a level */ } break; \f /* q-register numeric operations */ case 'u': if (!esp->flag1) ERROR(E_NAU); /* error if no arg */ else qreg[getqspec(0, getcmdc(trace_sw))].v = esp->val1; esp->flag1 = esp->flag2; /* command's "value" is 2nd arg */ esp->val1 = esp->val2; esp->flag2 = 0; /* clear 2nd arg */ esp->op = OP_START; break; case 'q': /* Qn is numeric val, :Qn is # of chars, mQn is mth char */ mm = getqspec((colonflag || esp->flag1), getcmdc(trace_sw)); /* read register name */ if (!(esp->flag1)) { esp->val1 = (colonflag) ? qreg[mm].z : qreg[mm].v; esp->flag1 = 1; } else /* esp->flag1 is already set */ { if ((esp->val1 >= 0) && (esp->val1 < qreg[mm].z)) /* char subscript within range? */ { for (ll = 0, aa.p = qreg[mm].f; ll < (esp->val1 / CELLSIZE); ll++) aa.p = aa.p->f; esp->val1 = (int) aa.p->ch[esp->val1 % CELLSIZE]; } else esp->val1 = -1; /* char position out of range */ esp->op = OP_START; /* consume argument */ } colonflag = 0; break; case '%': esp->val1 = (qreg[getqspec(0, getcmdc(trace_sw))].v += get_value(1)); /* add to q reg */ esp->flag1 = 1; break; \f /* move pointer */ case 'c': if (((tdot = dot + get_value(1)) < 0) || (tdot > z)) ERROR(E_POP); /* add arg to dot, default 1 */ else dot = tdot; esp->flag2 = 0; break; case 'r': if (((tdot = dot - get_value(1)) < 0) || (tdot > z)) ERROR(E_POP); /* add arg to dot, default 1 */ else dot = tdot; esp->flag2 = 0; break; case 'j': if (((tdot = get_value(0)) < 0) || (tdot > z)) ERROR(E_POP); /* add arg to dot, default 1 */ else dot = tdot; esp->flag2 = 0; break; case 'l': dot += lines(get_value(1)); break; /* number of chars until nth line feed */ case CTL (Q): esp->val1 = lines(get_value(1)); esp->flag1 = 1; break; /* print numeric value */ case '=': if (!esp->flag1) ERROR(E_NAE); /* error if no arg */ else { if (peekcmdc('=')) /* at least one more '=' */ { getcmdc(trace_sw); /* read past it */ if (peekcmdc('=')) /* another? */ { getcmdc(trace_sw); /* yes, read it too */ printf("%x", esp->val1); /* print in hex */ } else printf("%o", esp->val1); /* print in octal */ } else printf("%d", esp->val1); if (!colonflag) crlf(); esp->flag1 = esp->flag2 = colonflag = 0; esp->op = OP_START; if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */ } break; \f /* insert text */ case TAB: /* insert tab, then text */ if (ez_val & EZ_NOTABI) break; /* tab disabled */ if (esp->flag1) ERROR(E_IIA); /* can't have arg */ case 'i': /* insert text at pointer */ term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */ if (esp->flag1) /* if a nI$ command */ { if (!peekcmdc(term_char)) ERROR(E_IIA); /* next char must be term */ insert1(); /* first part of insert */ bb.p->ch[bb.c] = esp->val1 & 0177; /* insert character */ fwdcx(&bb); /* advance pointer and extend buffer if necessary */ ins_count = 1; /* save string length */ esp->op = OP_START; /* consume argument */ } else /* not a nI command: insert text */ { insert1(); /* initial insert operations */ if (command == TAB) /* TAB insert puts in a tab first */ { bb.p->ch[bb.c] = TAB; /* insert a tab */ fwdcx(&bb); /* advance pointer and maybe extend buffer */ } moveuntil(&cptr, &bb, term_char, &ins_count, cptr.z - cptr.dot, trace_sw); /* copy cmd str -> buffer */ if (command == TAB) ++ins_count; /* add 1 if a tab inserted */ cptr.dot += ins_count; /* indicate advance over that many chars */ } insert2(ins_count); /* finish insert */ getcmdc(trace_sw); /* flush terminating char */ colonflag = atflag = esp->flag1 = esp->flag2 = 0; /* clear args */ break; /* type text from text buffer */ case 't': for (ll = line_args(0, &aa); ll > 0; ll--) /* while there are chars to type */ { type_char(aa.p->ch[aa.c]); fwdc(&aa); } if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */ break; case 'v': if ((ll = get_value(1)) > 0) /* arg must be positive */ { mm = lines(1 - ll); /* find start */ nn = lines(ll) - mm; /* and number of chars */ set_pointer(dot + mm, &aa); /* pointer to start of text */ for (; nn > 0; nn--) /* as above */ { type_char(aa.p->ch[aa.c]); fwdc(&aa); } } if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */ break; \f /* type text from command string */ case CTL (A): term_char = (atflag) ? getcmdc(trace_sw) : CTL(A); /* set terminator */ while (getcmdc(0) != term_char) type_char(cmdc); /* output chars */ atflag = colonflag = esp->flag2 = esp->flag1 = 0; esp->op = OP_START; if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */ break; /* delete text */ case 'd': if (!esp->flag2) /* if only one argument */ { delete1(get_value(1)); /* delete chars (default is 1) */ break; } /* if two args, fall through to treat m,nD as m,nK */ case 'k': /* delete lines or chars */ ll = line_args(1, &aa); /* aa points to start, ll chars, leave dot at beginning */ delete1(ll); /* delete ll chars */ break; /* q-register text loading commands */ case CTL (U): mm = getqspec(0, getcmdc(trace_sw)); if (!colonflag) /* X, ^U commands destroy previous contents */ { dly_free_blist(qreg[mm].f); qreg[mm].f = NULL; qreg[mm].z = 0; } term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */ atflag = 0; /* clear flag */ if ((esp->flag1) || (!peekcmdc(term_char))) /* if an arg or a nonzero insert, find register */ { make_buffer(&qreg[mm]); /* attach a text buffer to the q register */ for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f); /* find end of reg */ bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0; } if (!(esp->flag1)) { moveuntil(&cptr, &bb, term_char, &ll, cptr.z - cptr.dot, trace_sw); cptr.dot += ll; /* indicate advance over that many chars */ qreg[mm].z += ll; /* update q-reg char count */ getcmdc(trace_sw); /* skip terminator */ } else { if (getcmdc(trace_sw) != term_char) ERROR(E_IIA); /* must be zero length string */ bb.p->ch[bb.c] = esp->val1; /* store char */ fwdcx(&bb); /* extend the register */ ++qreg[mm].z; esp->flag1 = 0; /* consume argument */ } colonflag = 0; break; \f case 'x': mm = getqspec(0, getcmdc(trace_sw)); if (!colonflag) /* X, ^U commands destroy previous contents */ { dly_free_blist(qreg[mm].f); /* return, but delayed (in case executing now) */ qreg[mm].f = NULL; qreg[mm].z = 0; } if (ll = line_args(0, &aa)) /* read args and move chars, if any */ { make_buffer(&qreg[mm]); /* attach a text buffer to the q register */ for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f); /* find end of reg */ bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0; movenchars(&aa, &bb, ll); qreg[mm].z += ll; /* update q-reg char count */ } colonflag = 0; break; case 'g': /* get q register */ if (qreg[mm = getqspec(1, getcmdc(trace_sw))].z) /* if any chars in it */ { cc.p = qreg[mm].f; /* point cc to start of reg */ cc.c = 0; if (colonflag) /* :Gx types q-reg */ { for (ll = qreg[mm].z; ll > 0; ll--) { type_char(cc.p->ch[cc.c]); /* type char */ fwdc(&cc); } } else { insert1(); /* set up for insert */ movenchars(&cc, &bb, qreg[mm].z); /* copy q reg text */ insert2(qreg[mm].z); /* finish insert */ } } colonflag = 0; break; \f /* q-register push and pop */ case '[': if (qsp > &qstack[QSTACKSIZE-1]) ERROR(E_PDO); /* stack full */ else { make_buffer(++qsp); /* increment stack ptr and put a text buffer there */ mm = getqspec(1, getcmdc(trace_sw)); /* get the q reg name */ aa.p = qreg[mm].f; /* point to the q register */ aa.c = 0; bb.p = qsp->f; /* point to the new list */ bb.c = 0; movenchars(&aa, &bb, qreg[mm].z); /* copy the text */ qsp->z = qreg[mm].z; /* and the length */ qsp->v = qreg[mm].v; /* and the value */ } break; case ']': mm = getqspec(1, getcmdc(trace_sw)); /* get reg name */ if (qsp < &qstack[0]) /* if stack empty */ { if (colonflag) /* :] returns 0 */ { esp->flag1 = 1; esp->val1 = 0; colonflag = 0; } else ERROR(E_CPQ); /* ] makes an error */ } else /* stack not empty */ { free_blist(qreg[mm].f); /* return orig contents of reg */ qreg[mm].f = qsp->f; /* substitute stack entry */ qsp->f->b = (struct buffcell *) &qreg[mm]; qsp->f = NULL; /* null out stack entry */ qreg[mm].z = qsp->z; qreg[mm].v = qsp->v; if (colonflag) { esp->flag1 = 1; /* :] returns -1 */ esp->val1 = -1; colonflag = 0; } --qsp; } break; \f case '\\': if (!(esp->flag1)) /* no argument; read number */ { ll = esp->val1 = 0; /* sign flag and initial value */ for (ctrl_s = 0; dot <= z; dot++, ctrl_s--) /* count digits; don't read beyond buffer */ { set_pointer(dot, &aa); /* point to dot */ if ((aa.p->ch[aa.c] == '+') || (aa.p->ch[aa.c] == '-')) { if (ll) break; /* second sign: quit */ else ll = aa.p->ch[aa.c]; /* first sign: save it */ } else { if (ctrl_r != 16) /* octal or decimal */ { /* stop if not a valid digit */ if ((!isdigit(aa.p->ch[aa.c])) || (aa.p->ch[aa.c] - '0' >= ctrl_r)) break; esp->val1 = esp->val1 * ctrl_r + (aa.p->ch[aa.c] - '0'); } else { if (!isxdigit(aa.p->ch[aa.c])) break; esp->val1 = esp->val1 * 16 + ( (isdigit(aa.p->ch[aa.c])) ? aa.p->ch[aa.c] - '0' : mapch_l[aa.p->ch[aa.c]] - 'a' + 10); } /* end of hex */ } /* end of digit processing */ } /* end of "for each char" */ if (ll == '-') esp->val1 = -(esp->val1); /* if minus sign */ esp->flag1 = 1; /* always returns a value */ } else /* argument: insert it as a digit string */ { if (ctrl_r == 8) sprintf(t_bcell.ch, "%o", esp->val1); /* print as digits */ else if (ctrl_r == 10) sprintf(t_bcell.ch, "%d", esp->val1); else sprintf(t_bcell.ch, "%x", esp->val1); insert1(); /* start insert */ cc.p = &t_bcell; /* point cc to the temp cell */ cc.c = 0; moveuntil(&cc, &bb, '\0', &ins_count, CELLSIZE-1, 0); /* copy the char string */ insert2(ins_count); /* finish the insert */ esp->flag1 = 0; /* consume argument */ esp->op = OP_START; } break; \f case CTL (T): /* type or input character */ if (esp->flag1) /* type */ { type_char(esp->val1); esp->flag1 = 0; if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */ } else { esp->val1 = (et_val & ET_NOWAIT) ? gettty_nowait() : gettty(); if (!(et_val & ET_NOECHO) && (esp->val1 > 0) && !inp_noterm) type_char(esp->val1); /* echo */ esp->flag1 = 1; } break; /* search commands */ case 's': /* search within buffer */ build_string(&sbuf); /* read the search string */ end_search ( do_search( setup_search() ) ); /* search */ break; case 'n': /* search through rest of file */ case '_': do_nsearch(command); /* call routine for N, _, E_ */ break; case 'o': /* branch to tag */ do_o(); break; \f /* file I/O commands */ case 'p': /* write a page, get next (ignore args for now) */ if (esp->flag1 && esp->flag2) /* if two args */ write_file(&aa, line_args(0, &aa), 0); /* write spec'd buffer with no FF */ else /* one arg */ { for (ll = get_value(1); ll > 0; ll--) /* get count and loop */ { set_pointer(0, &aa); if (peekcmdc('w')) write_file(&aa, z, 1); /* PW writes buffer, then FF */ else { write_file(&aa, z, ctrl_e); /* P writes buffer, FF if read in, then gets next page */ dot = z = 0; /* empty the buffer */ set_pointer(0, &aa); /* set a pointer to the beginning of the buffer */ buff_mod = 0; /* mark where new buffer starts */ esp->val1 = read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) ); /* read a page */ esp->flag1 = colonflag; } } } if (peekcmdc('w')) getcmdc(trace_sw); /* if a PW command, consume the W */ colonflag = 0; break; case 'y': /* get a page into buffer */ if (esp->flag1) ERROR(E_NYA); if ((z) && (!(ed_val & ED_YPROT))) ERROR(E_YCA); /* don't lose text */ dot = z = 0; /* clear buffer */ set_pointer(0, &aa); /* set a pointer to the beginning of the buffer */ buff_mod = 0; /* mark where new buffer starts */ read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) ); /* read a page */ esp->flag1 = colonflag; esp->op = OP_START; colonflag = 0; break; \f case 'a': /* append, or ascii value */ if (esp->flag1 && !colonflag) /* ascii value */ { ll = dot + esp->val1; /* set a pointer before addr'd char */ if ((ll >= 0) && (ll < z)) /* if character lies within buffer */ { set_pointer(ll, &aa); esp->val1 = (int) aa.p->ch[aa.c]; /* get char (flag already set) */ } else esp->val1 = -1; /* otherwise return -1 */ } else { set_pointer(z, &aa); /* set pointer to end of buffer */ if (z < buff_mod) buff_mod = z; /* mark where new buffer starts */ if (esp->flag1 && (esp->val1 <= 0)) ERROR(E_IAA); /* neg or 0 arg to :A */ read_file(&aa, &z, (esp->flag1 ? esp->val1 : 0) ); /* read a page */ esp->flag1 = colonflag; colonflag = 0; } esp->op = OP_START; break; /* window commands */ case 'w': do_window(0); /* this stuff is with the window driver */ break; case CTL (W): do_window(1); /* this is, too */ break; default: ERROR(E_ILL); /* invalid command */ } /* end of "switch" */ return; /* normal exit */ } /* end of exec_cmds1 */