home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume9 / teco / part03 / te_exec1.c next >
Encoding:
C/C++ Source or Header  |  1987-03-11  |  20.5 KB  |  714 lines

  1. /* TECO for Ultrix   Copyright 1986 Matt Fichtenbaum                        */
  2. /* This program and its components belong to GenRad Inc, Concord MA 01742    */
  3. /* They may be copied if this copyright notice is included                    */
  4.  
  5. /* te_exec1.c   continue executing commands   1/8/87 */
  6. #include "te_defs.h"
  7.  
  8. exec_cmds1()
  9.     {
  10.     char command;                    /* command character */
  11.     int cond;                        /* conditional in progress */
  12.  
  13.     switch (command = mapch_l[cmdc])
  14.         {
  15. /* operators */
  16.  
  17.         case '+':
  18.             esp->exp = (esp->flag1) ? esp->val1 : 0;
  19.             esp->flag1 = 0;
  20.             esp->op = OP_ADD;
  21.             break;
  22.  
  23.         case '-':
  24.             esp->exp = (esp->flag1) ? esp->val1 : 0;
  25.             esp->flag1 = 0;
  26.             esp->op = OP_SUB;
  27.             break;
  28.  
  29.         case '*':
  30.             esp->exp = (esp->flag1) ? esp->val1 : 0;
  31.             esp->flag1 = 0;
  32.             esp->op = OP_MULT;
  33.             break;
  34.  
  35.         case '/':
  36.             esp->exp = (esp->flag1) ? esp->val1 : 0;
  37.             esp->flag1 = 0;
  38.             esp->op = OP_DIV;
  39.             break;
  40.  
  41.         case '&':
  42.             esp->exp = (esp->flag1) ? esp->val1 : 0;
  43.             esp->flag1 = 0;
  44.             esp->op = OP_AND;
  45.             break;
  46.  
  47.         case '#':
  48.             esp->exp = (esp->flag1) ? esp->val1 : 0;
  49.             esp->flag1 = 0;
  50.             esp->op = OP_OR;
  51.             break;
  52.  
  53.         case ')':
  54.             if ((!esp->flag1) || (esp <= &estack[0])) ERROR(E_NAP);
  55.             --esp;
  56.             esp->val1 = (esp+1)->val1;    /* carry value from inside () */
  57.             esp->flag1 = 1;
  58.             break;
  59.         case ',':
  60.             if (!esp->flag1) ERROR(E_NAC);
  61.             else esp->val2 = esp->val1;
  62.             esp->flag2 = 1;
  63.             esp->flag1 = 0;
  64.             break;
  65.  
  66.         case CTL (_):
  67.             if (!esp->flag1) ERROR(E_NAB);
  68.             else esp->val1 = ~esp->val1;
  69.             break;
  70.  
  71. /* radix control */
  72.  
  73.         case CTL (D):
  74.             ctrl_r = 10;
  75.             esp->flag1 = 0;
  76.             esp->op = OP_START;
  77.             break;
  78.  
  79.         case CTL (O):
  80.             ctrl_r = 8;
  81.             esp->flag1 = 0;
  82.             esp->op = OP_START;
  83.             break;
  84.  
  85.         case CTL (R):
  86.             if (!esp->flag1)    /* fetch it */
  87.                 {
  88.                 esp->val1 = ctrl_r;
  89.                 esp->flag1 = 1;
  90.                 }
  91.             else
  92.                 {
  93.                 if ((esp->val1 != 8) && (esp->val1 != 10) && (esp->val1 != 16)) ERROR(E_IRA);
  94.                 ctrl_r = esp->val1;
  95.                 esp->flag1 = 0;
  96.                 esp->op = OP_START;
  97.                 }
  98.             break;
  99.  
  100. /* other commands */
  101.  
  102.         case CTL (C):            /* 1 ^C stops macro execution, 2 exit */
  103.             if (peekcmdc(CTL (C))) exitflag = -1;        /* 2 ^C: stop execution and exit */
  104.             else if (msp <= &mstack[0]) exitflag = 1;    /* 1 ^C: in command string: stop execution */
  105.             else --msp;                                    /*         in a macro - pop it */
  106.             break;
  107.  
  108.         case CTL (X):            /* search mode flag */
  109.             set_var(&ctrl_x);
  110.             break;
  111.  
  112.         case 'e':
  113.             do_e();
  114.             break;
  115.  
  116.         case 'f':
  117.             do_f();
  118.             break;
  119. /* macro call, iteration, conditional */
  120.  
  121.         case 'm':                /* macro call */
  122.             mm = getqspec(0, getcmdc(trace_sw));    /* read the macro name */
  123.             if (msp > &mstack[MSTACKSIZE-1]) ERROR(E_PDO);    /* check room for another level */
  124.             ++msp;                    /* push stack */
  125.             cptr.p = qreg[mm].f;    /* to stack entry, put q-reg text start */
  126.             cptr.flag = cptr.c = cptr.dot = 0;    /* initial char position, iteration flag */
  127.             cptr.z = qreg[mm].z;    /* number of chars in macro */
  128.             break;
  129.  
  130.         case '<':                /* begin iteration */
  131.             if ((esp->flag1) && (esp->val1 <= 0))        /* if this is not to be executed */
  132.                 find_enditer();                            /* just skip the intervening stuff */
  133.             else
  134.                 {
  135.                 if (!cptr.il)        /* does this macro have an iteration list? */
  136.                     {
  137.                     cptr.il = (struct is *) get_dcell();    /* no, make one for it */
  138.                     cptr.il->b = NULL;                        /* with NULL reverse pointer */
  139.                     }
  140.                 else if (cptr.flag & F_ITER)        /* is there an iteration in process? */
  141.                     {
  142.                     if (!cptr.il->f)                /* yes, if it has no forward pointer */
  143.                         {
  144.                         cptr.il->f = (struct is *) get_dcell();        /* append a cell to the iteration list */
  145.                         cptr.il->f->b = cptr.il;                    /* and link it in */
  146.                         }
  147.                     cptr.il = cptr.il->f;                        /* and advance the iteration list pointer to it */
  148.                     }
  149.                 cptr.flag |= F_ITER;                /* set iteration flag */
  150.                 cptr.il->p = cptr.p;                /* save start of iteration */
  151.                 cptr.il->c = cptr.c;
  152.                 cptr.il->dot = cptr.dot;
  153.                 if (cptr.il->dflag = esp->flag1)    /* if there is an argument, set the "def iter" flag */
  154.                     {
  155.                     cptr.il->count = esp->val1;        /* save the count */
  156.                     esp->flag1 = 0;                    /* and consume the arg */
  157.                     }
  158.                 }
  159.             break;
  160.  
  161.         case '>':                /* end iteration */
  162.             if (!(cptr.flag & F_ITER)) ERROR(E_BNI);        /* error if > not in iteration */
  163.             pop_iteration(0);        /* decrement count and pop conditionally */
  164.             esp->flag1 = esp->flag2 = 0;    /* consume arguments */
  165.             esp->op = OP_START;
  166.             break;
  167.  
  168.         case ';':                /* semicolon iteration exit */
  169.             if (!(cptr.flag &F_ITER)) ERROR(E_SNI);        /* error if ; not in iteration */
  170.             if ( ( ((esp->flag1) ? esp->val1 : srch_result) >= 0) ? (!colonflag) : colonflag)    /* if exit */
  171.                 {
  172.                 find_enditer();            /* get to end of iteration */
  173.                 pop_iteration(1);        /* and pop unconditionally */
  174.                 }
  175.             esp->flag1 = colonflag = 0;        /* consume arg and colon */
  176.             esp->op = OP_START;
  177.             break;
  178. /* conditionals */
  179.  
  180.         case '"':
  181.             if (!esp->flag1) ERROR(E_NAQ);        /* must be an argument */
  182.             esp->flag1 = 0;                    /* consume argument */
  183.             esp->op = OP_START;
  184.             switch (mapch_l[getcmdc(trace_sw)])
  185.                 {
  186.                 case 'a':
  187.                     cond = isalpha(esp->val1);
  188.                     break;
  189.  
  190.                 case 'c':
  191.                     cond = isalpha(esp->val1) | (esp->val1 == '$') | (esp->val1 == '.');
  192.                     break;
  193.  
  194.                 case 'd':
  195.                     cond = isdigit(esp->val1);
  196.                     break;
  197.  
  198.                 case 'e':
  199.                 case 'f':
  200.                 case 'u':
  201.                 case '=':
  202.                     cond = !(esp->val1);
  203.                     break;
  204.  
  205.                 case 'g':
  206.                 case '>':
  207.                     cond = (esp->val1 > 0);
  208.                     break;
  209.  
  210.                 case 'l':
  211.                 case 's':
  212.                 case 't':
  213.                 case '<':
  214.                     cond = (esp->val1 < 0);
  215.                     break;
  216.  
  217.                 case 'n':
  218.                     cond = esp->val1;
  219.                     break;
  220.  
  221.                 case 'r':
  222.                     cond = isalnum(esp->val1);
  223.                     break;
  224.  
  225.                 case 'v':
  226.                     cond = islower(esp->val1);
  227.                     break;
  228.  
  229.                 case 'w':
  230.                     cond = isupper(esp->val1);
  231.                     break;
  232.  
  233.                 default:
  234.                     ERROR(E_IQC);
  235.                 }
  236.             if (!cond)            /* if this conditional isn't satisfied */
  237.                 {
  238.                 for (ll = 1; ll > 0;)        /* read to matching | or ' */
  239.                     {
  240.                     while ((skipto(0) != '"') && (skipc != '|') && (skipc != '\''));    /* skip chars */
  241.                     if (skipc == '"')       ++ll;    /* start another level */
  242.                     else if (skipc == '\'') --ll;    /* end a level */
  243.                     else if (ll == 1) break;        /* "else" (|): if on this level, start executing */
  244.                     }
  245.                 }
  246.             break;
  247.  
  248.         case '\'':                /* end of conditional */
  249.             break;                /* ignore it if executing */
  250.  
  251.         case '|':                /* "else" clause */
  252.             for (ll = 1; ll > 0;)            /* skip to matching ' */
  253.                 {
  254.                 while ((skipto(0) != '"') && (skipc != '\''));    /* skip chars */
  255.                 if (skipc == '"') ++ll;            /* start another level */
  256.                 else             --ll;            /* end a level */
  257.                 }
  258.             break;
  259. /* q-register numeric operations */
  260.  
  261.         case 'u':
  262.             if (!esp->flag1) ERROR(E_NAU);    /* error if no arg */
  263.             else qreg[getqspec(0, getcmdc(trace_sw))].v = esp->val1;
  264.             esp->flag1 = esp->flag2;        /* command's "value" is 2nd arg */
  265.             esp->val1 = esp->val2;
  266.             esp->flag2 = 0;                    /* clear 2nd arg */
  267.             esp->op = OP_START;
  268.             break;
  269.  
  270.         case 'q':        /* Qn is numeric val, :Qn is # of chars, mQn is mth char */
  271.             mm = getqspec((colonflag || esp->flag1), getcmdc(trace_sw));        /* read register name */
  272.             if (!(esp->flag1))
  273.                 {
  274.                 esp->val1 = (colonflag) ? qreg[mm].z : qreg[mm].v;
  275.                 esp->flag1 = 1;
  276.                 }
  277.             else        /* esp->flag1 is already set */
  278.                 {
  279.                 if ((esp->val1 >= 0) && (esp->val1 < qreg[mm].z))    /* char subscript within range? */
  280.                     {
  281.                     for (ll = 0, aa.p = qreg[mm].f; ll < (esp->val1 / CELLSIZE); ll++) aa.p = aa.p->f;
  282.                     esp->val1 = (int) aa.p->ch[esp->val1 % CELLSIZE];
  283.                     }
  284.                 else esp->val1 = -1;    /* char position out of range */
  285.                 esp->op = OP_START;        /* consume argument */
  286.                 }
  287.             colonflag = 0;
  288.             break;
  289.  
  290.         case '%':
  291.             esp->val1 = (qreg[getqspec(0, getcmdc(trace_sw))].v += get_value(1));    /* add to q reg */
  292.             esp->flag1 = 1;
  293.             break;
  294. /* move pointer */
  295.  
  296.         case 'c':
  297.             if (((tdot = dot + get_value(1)) < 0) || (tdot > z))
  298.                 ERROR(E_POP);    /* add arg to dot, default 1 */
  299.             else dot = tdot;
  300.             esp->flag2 = 0;
  301.             break;
  302.  
  303.         case 'r':
  304.             if (((tdot = dot - get_value(1)) < 0) || (tdot > z))
  305.                 ERROR(E_POP);    /* add arg to dot, default 1 */
  306.             else dot = tdot;
  307.             esp->flag2 = 0;
  308.             break;
  309.  
  310.         case 'j':
  311.             if (((tdot = get_value(0)) < 0) || (tdot > z))
  312.                 ERROR(E_POP);    /* add arg to dot, default 1 */
  313.             else dot = tdot;
  314.             esp->flag2 = 0;
  315.             break;
  316.  
  317.         case 'l':
  318.             dot += lines(get_value(1));
  319.             break;
  320.  
  321. /* number of chars until nth line feed */
  322.  
  323.         case CTL (Q):
  324.             esp->val1 = lines(get_value(1));
  325.             esp->flag1 = 1;
  326.             break;
  327.  
  328. /* print numeric value */
  329.  
  330.         case '=':
  331.             if (!esp->flag1) ERROR(E_NAE);    /* error if no arg */
  332.             else
  333.                 {
  334.                 if (peekcmdc('='))        /* at least one more '=' */
  335.                     {
  336.                     getcmdc(trace_sw);        /* read past it */
  337.                     if (peekcmdc('='))        /* another? */
  338.                         {
  339.                         getcmdc(trace_sw);            /* yes, read it too */
  340.                         printf("%x", esp->val1);    /* print in hex */
  341.                         }
  342.                     else printf("%o", esp->val1);    /* print in octal */
  343.                     }
  344.                 else printf("%d", esp->val1);
  345.                 if (!colonflag) crlf();
  346.                 esp->flag1 = esp->flag2 =  colonflag = 0;
  347.                 esp->op = OP_START;
  348.                 if (!WN_scroll) window(WIN_REDRAW);            /* if not in scroll mode, force full redraw on next refresh */
  349.                 }
  350.             break;
  351. /* insert text */
  352.  
  353.         case TAB:                    /* insert tab, then text */
  354.             if (ez_val & EZ_NOTABI) break;        /* tab disabled */
  355.             if (esp->flag1) ERROR(E_IIA);        /* can't have arg */
  356.  
  357.         case 'i':                    /* insert text at pointer */
  358.             term_char = (atflag) ? getcmdc(trace_sw) : ESC;        /* set terminator */
  359.             if (esp->flag1)        /* if a nI$ command */
  360.                 {
  361.                 if (!peekcmdc(term_char)) ERROR(E_IIA);    /* next char must be term */
  362.                 insert1();            /* first part of insert */
  363.                 bb.p->ch[bb.c] = esp->val1 & 0177;        /* insert character */
  364.                 fwdcx(&bb);            /* advance pointer and extend buffer if necessary */
  365.                 ins_count = 1;        /* save string length */
  366.                 esp->op = OP_START;    /* consume argument */
  367.                 }
  368.             else                    /* not a nI command: insert text */
  369.                 {
  370.                 insert1();            /* initial insert operations */
  371.  
  372.                 if (command == TAB)            /* TAB insert puts in a tab first */
  373.                     {
  374.                     bb.p->ch[bb.c] = TAB;    /* insert a tab */
  375.                     fwdcx(&bb);                /* advance pointer and maybe extend buffer */
  376.                     }
  377.                 moveuntil(&cptr, &bb, term_char, &ins_count, cptr.z - cptr.dot, trace_sw);    /* copy cmd str -> buffer */
  378.                 if (command == TAB) ++ins_count;    /* add 1 if a tab inserted */
  379.                 cptr.dot += ins_count;    /* indicate advance over that many chars */
  380.                 }
  381.             insert2(ins_count);        /* finish insert */
  382.             getcmdc(trace_sw);        /* flush terminating char */
  383.             colonflag = atflag = esp->flag1 = esp->flag2 = 0;    /* clear args */
  384.             break;
  385.  
  386. /* type text from text buffer */
  387.     
  388.         case 't':
  389.             for (ll = line_args(0, &aa); ll > 0; ll--)    /* while there are chars to type */
  390.                 {
  391.                 type_char(aa.p->ch[aa.c]);
  392.                 fwdc(&aa);
  393.                 }
  394.             if (!WN_scroll) window(WIN_REDRAW);            /* if not in scroll mode, force full redraw on next refresh */
  395.             break;
  396.  
  397.         case 'v':
  398.             if ((ll = get_value(1)) > 0)        /* arg must be positive */
  399.                 {
  400.                 mm = lines(1 - ll);                    /* find start */
  401.                 nn = lines(ll) - mm;                /* and number of chars */
  402.                 set_pointer(dot + mm, &aa);            /* pointer to start of text */
  403.                 for (; nn > 0; nn--)                /* as above */
  404.                     {
  405.                     type_char(aa.p->ch[aa.c]);
  406.                     fwdc(&aa);
  407.                     }
  408.                 }
  409.             if (!WN_scroll) window(WIN_REDRAW);            /* if not in scroll mode, force full redraw on next refresh */
  410.             break;
  411. /* type text from command string */
  412.  
  413.         case CTL (A):
  414.             term_char = (atflag) ? getcmdc(trace_sw) : CTL(A);        /* set terminator */
  415.             while (getcmdc(0) != term_char) type_char(cmdc);    /* output chars */
  416.             atflag = colonflag = esp->flag2 = esp->flag1 = 0;
  417.             esp->op = OP_START;
  418.             if (!WN_scroll) window(WIN_REDRAW);            /* if not in scroll mode, force full redraw on next refresh */
  419.             break;
  420.  
  421.     /* delete text */
  422.  
  423.         case 'd':
  424.             if (!esp->flag2)                /* if only one argument */
  425.                 {
  426.                 delete1(get_value(1));            /* delete chars (default is 1) */
  427.                 break;
  428.                 }                /* if two args, fall through to treat m,nD as m,nK */
  429.  
  430.         case 'k':                    /* delete lines or chars */
  431.             ll = line_args(1, &aa);    /* aa points to start, ll chars, leave dot at beginning */
  432.             delete1(ll);            /* delete ll chars */
  433.             break;
  434.  
  435. /* q-register text loading commands */
  436.  
  437.         case CTL (U):
  438.             mm = getqspec(0, getcmdc(trace_sw));
  439.             if (!colonflag)            /* X, ^U commands destroy previous contents */
  440.                 {
  441.                 dly_free_blist(qreg[mm].f);
  442.                 qreg[mm].f = NULL;
  443.                 qreg[mm].z = 0;
  444.                 }
  445.             term_char = (atflag) ? getcmdc(trace_sw) : ESC;        /* set terminator */
  446.             atflag = 0;            /* clear flag */
  447.  
  448.             if ((esp->flag1) || (!peekcmdc(term_char)))        /* if an arg or a nonzero insert, find register */
  449.                 {
  450.                 make_buffer(&qreg[mm]);            /* attach a text buffer to the q register */
  451.                 for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f);    /* find end of reg */
  452.                 bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0;
  453.                 }
  454.             if (!(esp->flag1))
  455.                 {
  456.                 moveuntil(&cptr, &bb, term_char, &ll, cptr.z - cptr.dot, trace_sw);
  457.                 cptr.dot += ll;            /* indicate advance over that many chars */
  458.                 qreg[mm].z += ll;        /* update q-reg char count */
  459.                 getcmdc(trace_sw);        /* skip terminator */
  460.                 }
  461.             else
  462.                 {
  463.                 if (getcmdc(trace_sw) != term_char) ERROR(E_IIA);    /* must be zero length string */
  464.                 bb.p->ch[bb.c] = esp->val1;                /* store char */
  465.                 fwdcx(&bb);                /* extend the register */
  466.                 ++qreg[mm].z;
  467.                 esp->flag1 = 0;            /* consume argument */
  468.                 }
  469.             colonflag = 0;
  470.             break;
  471.         case 'x':
  472.             mm = getqspec(0, getcmdc(trace_sw));
  473.             if (!colonflag)            /* X, ^U commands destroy previous contents */
  474.                 {
  475.                 dly_free_blist(qreg[mm].f);        /* return, but delayed (in case executing now) */
  476.                 qreg[mm].f = NULL;
  477.                 qreg[mm].z = 0;
  478.                 }
  479.  
  480.             if (ll = line_args(0, &aa))        /* read args and move chars, if any */
  481.                 {
  482.                 make_buffer(&qreg[mm]);            /* attach a text buffer to the q register */
  483.                 for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f);    /* find end of reg */
  484.                 bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0;
  485.  
  486.                 movenchars(&aa, &bb, ll);
  487.                 qreg[mm].z += ll;        /* update q-reg char count */
  488.                 }
  489.             colonflag = 0;
  490.             break;
  491.  
  492.         case 'g':                /* get q register */
  493.             if (qreg[mm = getqspec(1, getcmdc(trace_sw))].z)    /* if any chars in it */
  494.                 {
  495.                 cc.p = qreg[mm].f;        /* point cc to start of reg */
  496.                 cc.c = 0;
  497.                 if (colonflag)        /* :Gx types q-reg */
  498.                     {
  499.                     for (ll = qreg[mm].z; ll > 0; ll--)
  500.                         {
  501.                         type_char(cc.p->ch[cc.c]);    /* type char */
  502.                         fwdc(&cc);
  503.                         }
  504.                     }
  505.                 else
  506.                     {
  507.                     insert1();                /* set up for insert */
  508.                     movenchars(&cc, &bb, qreg[mm].z);    /* copy q reg text */
  509.                     insert2(qreg[mm].z);    /* finish insert */
  510.                     }
  511.                 }
  512.             colonflag = 0;
  513.             break;
  514. /* q-register push and pop */
  515.  
  516.         case '[':
  517.             if (qsp > &qstack[QSTACKSIZE-1]) ERROR(E_PDO);        /* stack full */
  518.             else
  519.                 {
  520.                 make_buffer(++qsp);        /* increment stack ptr and put a text buffer there */
  521.                 mm = getqspec(1, getcmdc(trace_sw));        /* get the q reg name */
  522.  
  523.                 aa.p = qreg[mm].f;            /* point to the q register */
  524.                 aa.c = 0;
  525.                 bb.p = qsp->f;                /* point to the new list */
  526.                 bb.c = 0;
  527.                 movenchars(&aa, &bb, qreg[mm].z);    /* copy the text */
  528.                 qsp->z = qreg[mm].z;        /* and the length */
  529.                 qsp->v = qreg[mm].v;        /* and the value */
  530.                 }
  531.             break;
  532.  
  533.         case ']':
  534.             mm = getqspec(1, getcmdc(trace_sw));        /* get reg name */
  535.             if (qsp < &qstack[0])                /* if stack empty */
  536.                 {
  537.                 if (colonflag)                    /* :] returns 0 */
  538.                     {
  539.                     esp->flag1 = 1;
  540.                     esp->val1 = 0;
  541.                     colonflag = 0;
  542.                     }
  543.                 else ERROR(E_CPQ);                /* ] makes an error */
  544.                 }
  545.             else                                    /* stack not empty */
  546.                 {
  547.                 free_blist(qreg[mm].f);            /* return orig contents of reg */
  548.                 qreg[mm].f = qsp->f;            /* substitute stack entry */
  549.                 qsp->f->b = (struct buffcell *) &qreg[mm];
  550.                 qsp->f = NULL;                    /* null out stack entry */
  551.                 qreg[mm].z = qsp->z;
  552.                 qreg[mm].v = qsp->v;
  553.                 if (colonflag)
  554.                     {
  555.                     esp->flag1 = 1;                /* :] returns -1 */
  556.                     esp->val1 = -1;
  557.                     colonflag = 0;
  558.                     }
  559.                 --qsp;
  560.                 }
  561.             break;
  562.         case '\\':
  563.             if (!(esp->flag1))        /* no argument; read number */
  564.                 {
  565.                 ll = esp->val1 = 0;            /* sign flag and initial value */
  566.                 for (ctrl_s = 0; dot <= z; dot++, ctrl_s--)        /* count digits; don't read beyond buffer */
  567.                     {
  568.                     set_pointer(dot, &aa);    /* point to dot */
  569.                     if ((aa.p->ch[aa.c] == '+') || (aa.p->ch[aa.c] == '-'))
  570.                         {
  571.                         if (ll) break;        /* second sign: quit */
  572.                         else ll = aa.p->ch[aa.c];    /* first sign: save it */
  573.                         }
  574.                     else
  575.                         {
  576.                         if (ctrl_r != 16)    /* octal or decimal */
  577.                             {                    /* stop if not a valid digit */
  578.                             if ((!isdigit(aa.p->ch[aa.c])) || (aa.p->ch[aa.c] - '0' >= ctrl_r)) break;
  579.                             esp->val1 = esp->val1 * ctrl_r + (aa.p->ch[aa.c] - '0');
  580.                             }
  581.                         else
  582.                             {
  583.                             if (!isxdigit(aa.p->ch[aa.c])) break;
  584.                             esp->val1 = esp->val1 * 16 + ( (isdigit(aa.p->ch[aa.c])) ?
  585.                                                 aa.p->ch[aa.c] - '0' : mapch_l[aa.p->ch[aa.c]] - 'a' + 10);
  586.                             }        /* end of hex */
  587.                         }        /* end of digit processing */
  588.                     }        /* end of "for each char" */
  589.                 if (ll == '-') esp->val1 = -(esp->val1);    /* if minus sign */
  590.                 esp->flag1 = 1;                /* always returns a value */
  591.                 }
  592.  
  593.             else                    /* argument: insert it as a digit string */
  594.                 {
  595.                 if (ctrl_r == 8)        sprintf(t_bcell.ch, "%o", esp->val1);    /* print as digits */
  596.                 else if (ctrl_r == 10)    sprintf(t_bcell.ch, "%d", esp->val1);
  597.                 else                    sprintf(t_bcell.ch, "%x", esp->val1);
  598.                 insert1();            /* start insert */
  599.                 cc.p = &t_bcell;    /* point cc to the temp cell */
  600.                 cc.c = 0;
  601.                 moveuntil(&cc, &bb, '\0', &ins_count, CELLSIZE-1, 0);    /* copy the char string */
  602.                 insert2(ins_count);    /* finish the insert */
  603.                 esp->flag1 = 0;        /* consume argument */
  604.                 esp->op = OP_START;
  605.                 }
  606.             break;
  607.         case CTL (T):            /* type or input character */
  608.             if (esp->flag1)        /* type */
  609.                 {
  610.                 type_char(esp->val1);
  611.                 esp->flag1 = 0;
  612.                 if (!WN_scroll) window(WIN_REDRAW);            /* if not in scroll mode, force full redraw on next refresh */
  613.                 }
  614.             else
  615.                 {
  616.                 esp->val1 = (et_val & ET_NOWAIT) ? gettty_nowait() : gettty();
  617.                 if (!(et_val & ET_NOECHO) && (esp->val1 > 0) && !inp_noterm) type_char(esp->val1);        /* echo */
  618.                 esp->flag1 = 1;
  619.                 }
  620.             break;
  621.  
  622. /* search commands */
  623.  
  624.         case 's':                    /* search within buffer */
  625.             build_string(&sbuf);    /* read the search string */
  626.             end_search (  do_search( setup_search() )  );        /* search */
  627.             break;
  628.  
  629.         case 'n':                    /* search through rest of file */
  630.         case '_':
  631.             do_nsearch(command);    /* call routine for N, _, E_ */
  632.             break;
  633.  
  634.         case 'o':                    /* branch to tag */
  635.             do_o();
  636.             break;
  637. /* file I/O commands */
  638.  
  639.         case 'p':                    /* write a page, get next (ignore args for now) */
  640.             if (esp->flag1 && esp->flag2)    /* if two args */
  641.                 write_file(&aa, line_args(0, &aa), 0);        /* write spec'd buffer with no FF */
  642.             else                            /* one arg */
  643.                 {
  644.                 for (ll = get_value(1);    ll > 0; ll--)    /* get count and loop */
  645.                     {
  646.                     set_pointer(0, &aa);
  647.                     if (peekcmdc('w')) write_file(&aa, z, 1);    /* PW writes buffer, then FF */
  648.                     else
  649.                         {
  650.                         write_file(&aa, z, ctrl_e);        /* P writes buffer, FF if read in, then gets next page */
  651.                         dot = z = 0;            /* empty the buffer */
  652.                         set_pointer(0, &aa);    /* set a pointer to the beginning of the buffer */
  653.                         buff_mod = 0;            /* mark where new buffer starts */
  654.                         esp->val1 = read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) );    /* read a page */
  655.                         esp->flag1 = colonflag;
  656.                         }
  657.                     }
  658.                 }
  659.             if (peekcmdc('w')) getcmdc(trace_sw);        /* if a PW command, consume the W */
  660.             colonflag = 0;
  661.             break;
  662.  
  663.         case 'y':                    /* get a page into buffer */
  664.             if (esp->flag1) ERROR(E_NYA);
  665.             if ((z) && (!(ed_val & ED_YPROT))) ERROR(E_YCA);    /* don't lose text */
  666.             dot = z = 0;            /* clear buffer */
  667.             set_pointer(0, &aa);    /* set a pointer to the beginning of the buffer */
  668.             buff_mod = 0;            /* mark where new buffer starts */
  669.             read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) );        /* read a page */
  670.             esp->flag1 = colonflag;
  671.             esp->op = OP_START;
  672.             colonflag = 0;
  673.             break;
  674.         case 'a':                    /* append, or ascii value */
  675.             if (esp->flag1 && !colonflag)        /* ascii value */
  676.                 {
  677.                 ll = dot + esp->val1;        /* set a pointer before addr'd char */
  678.                 if ((ll >= 0) && (ll < z))    /* if character lies within buffer */
  679.                     {
  680.                     set_pointer(ll, &aa);
  681.                     esp->val1 = (int) aa.p->ch[aa.c];    /* get char (flag already set) */
  682.                     }
  683.                 else esp->val1 = -1;        /* otherwise return -1 */
  684.                 }
  685.             else
  686.                 {
  687.                 set_pointer(z, &aa);                /* set pointer to end of buffer */
  688.                 if (z < buff_mod) buff_mod = z;            /* mark where new buffer starts */
  689.                 if (esp->flag1 && (esp->val1 <= 0)) ERROR(E_IAA);        /* neg or 0 arg to :A */
  690.                 read_file(&aa, &z, (esp->flag1 ? esp->val1 : 0) );        /* read a page */
  691.                 esp->flag1 = colonflag;
  692.                 colonflag = 0;
  693.                 }
  694.             esp->op = OP_START;
  695.             break;
  696.  
  697. /* window commands */
  698.  
  699.         case 'w':
  700.             do_window(0);                    /* this stuff is with the window driver */
  701.             break;
  702.  
  703.         case CTL (W):
  704.             do_window(1);                    /* this is, too */
  705.             break;
  706.  
  707.         default:
  708.             ERROR(E_ILL);                    /* invalid command */
  709.  
  710.         }        /* end of "switch" */
  711.     return;        /* normal exit */
  712.     }            /* end of exec_cmds1 */
  713.  
  714.