Annotation of researchv10dc/cmd/icon/src/iconx/interp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * The intepreter proper.
                      3:  */
                      4: 
                      5: /*
                      6:  * Instrumentation selection is based on Instr_level, which is given
                      7:  * as a product of prime numbers.
                      8:  */
                      9: #ifndef Instr
                     10: #define Instr 997
                     11: #endif Instr
                     12: #ifndef Instr_level
                     13: #define Instr_level    2
                     14: #endif Instr_level
                     15: 
                     16: #include "../h/rt.h"
                     17: #include "gc.h"
                     18: #include "../h/opdef.h"
                     19: 
                     20: /*
                     21:  * Istate variables.
                     22:  */
                     23: struct pf_marker *pfp;         /* Procedure frame pointer */
                     24: struct ef_marker *efp;         /* Expression frame pointer */
                     25: struct gf_marker *gfp;         /* Generator frame pointer */
                     26: word *ipc;                     /* Interpreter program counter */
                     27: struct descrip *argp;          /* Pointer to argument zero */
                     28: word *sp;                      /* Stack pointer */
                     29: extern int mstksize;           /* Size of main stack */
                     30: int ilevel;                    /* Depth of recursion in interp() */
                     31: 
                     32: #if (Instr % Instr_level) == 0
                     33: int maxilevel;                 /* Maximum ilevel */
                     34: word *maxsp;                   /* Maximum interpreter sp */
                     35: #endif Instr
                     36: 
                     37: extern word *stack;            /* Interpreter stack */
                     38: word *stackend;                        /* End of main interpreter stack */
                     39: 
                     40: #ifdef MSDOS
                     41: #ifdef LPTR
                     42: static union {
                     43:        char *stkadr;
                     44:        word stkint;
                     45:    } stkword;
                     46: #define PushAVal(v)  {sp++; \
                     47:                      stkword.stkadr = (char *)(v); \
                     48:                      *sp = stkword.stkint;}
                     49: #else LPTR
                     50: #define PushAVal PushVal
                     51: #endif LPTR
                     52: #else MSDOS
                     53: #define PushAVal PushVal
                     54: #endif MSDOS
                     55: 
                     56: /*
                     57:  * Initial icode sequence. This is used to invoke the main procedure with one
                     58:  *  operand.  If main returns, the Op_Quit is executed.
                     59:  */
                     60: word istart[3] = {Op_Invoke, 1, Op_Quit};
                     61: word mterm = Op_Quit;
                     62: 
                     63: /*
                     64:  * The tended descriptors.
                     65:  */
                     66: struct descrip tended[6];
                     67: 
                     68: /*
                     69:  * Descriptor to hold result for eret across potential interp unwinding.
                     70:  */
                     71: struct descrip eret_tmp;
                     72: /*
                     73:  * Last co-expression action.
                     74:  */
                     75: int coexp_act;
                     76: struct descrip *xargp;
                     77: 
                     78: main(argc, argv)
                     79: int argc; char **argv;
                     80: {
                     81:    int i;
                     82:    extern int tallyopt;
                     83: 
                     84: #if (Instr % Instr_level) == 0
                     85:    maxilevel = 0;
                     86:    maxsp = 0;
                     87: #endif Instr
                     88: 
                     89: #ifdef VMS
                     90:    redirect(&argc, argv, 0);
                     91: #endif VMS
                     92: 
                     93:    /*
                     94:     * Set tallying flag if -T option given
                     95:     */
                     96:    if (!strcmp(argv[1],"-T")) {
                     97:       tallyopt = 1;
                     98:       argc--;
                     99:       argv++;
                    100:       }
                    101: 
                    102: 
                    103:    /*
                    104:     * Call init with the name of the file to interpret.
                    105:     */
                    106:    init(argv[1]);
                    107: 
                    108:    /*
                    109:     *  Point sp at word after b_coexpr block for &main, point ipc at initial
                    110:     *   icode segment, and clear the gfp.
                    111:     */
                    112:    stackend = stack + mstksize/WordSize;
                    113:    sp = stack + Wsizeof(struct b_coexpr);
                    114:    ipc = istart;
                    115:    gfp = 0;
                    116: 
                    117:    /*
                    118:     * Set up expression frame marker to contain execution of the
                    119:     *  main procedure.  If failure occurs in this context, control
                    120:     *  is transferred to mterm, the address of an Op_Quit.
                    121:     */
                    122:    efp = (struct ef_marker *)(sp);
                    123:    efp->ef_failure = &mterm;
                    124:    efp->ef_gfp = 0;
                    125:    efp->ef_efp = 0;
                    126:    efp->ef_ilevel = 1;
                    127:    sp += Wsizeof(*efp) - 1;
                    128: 
                    129:    /*
                    130:     * The first global variable holds the value of "main".  If it
                    131:     *  is not of type procedure, this is noted as run-time error 117.
                    132:     *  Otherwise, this value is pushed on the stack.
                    133:     */
                    134:    if (globals[0].dword != D_Proc)
                    135:       runerr(117, NULL);
                    136:    PushDesc(globals[0]);
                    137: 
                    138:    /*
                    139:     * Main is to be invoked with one argument, a list of the command
                    140:     *  line arguments.  The command line arguments are pushed on the
                    141:     *  stack as a series of descriptors and llist is called to create
                    142:     *  the list.  The null descriptor first pushed serves as Arg0 for
                    143:     *  llist and receives the result of the computation.
                    144:     */
                    145:    PushNull;
                    146:    argp = (struct descrip *)(sp - 1);
                    147:    for (i = 2; i < argc; i++) {
                    148:       PushVal(strlen(argv[i]));
                    149:       PushAVal(argv[i]);
                    150:       }
                    151:    llist(argc - 2, argp);
                    152:    sp = (word *)argp + 1;
                    153:    argp = 0;
                    154: 
                    155:    /*
                    156:     * Start things rolling by calling interp.  This call to interp
                    157:     *  returns only if an Op_Quit is executed.  If this happens,
                    158:     *  c_exit() is called to wrap things up.
                    159:     */
                    160:    interp(0,NULL);
                    161:    c_exit(NormalExit);
                    162: }
                    163: 
                    164: /*
                    165:  * Macros for use inside the main loop of the interpreter.
                    166:  */
                    167: 
                    168: /*
                    169:  * Setup_Op sets things up for a call to the C function for an operator.
                    170:  */
                    171: #define Setup_Op(nargs)  \
                    172:    rargp = (struct descrip *) (rsp - 1) - nargs; \
                    173:    ExInterp;
                    174: 
                    175: /*
                    176:  * Call_Op(n) calls an unconditional operator. The C routine associated
                    177:  *  with the current opcode is called. After the routine performs the operation
                    178:  *  and returns, the stack pointer is reset to point to the result.
                    179:  */
                    180: #define Call_Op(n) (*(optab[op]))(rargp); \
                    181:          rsp = (word *) rargp + 1;
                    182: 
                    183: /*
                    184:  * Call_Cond(n) calls a conditional operator. The C routine associated
                    185:  * with the current opcode is called.  The routine returns a signal of
                    186:  * success or failure.  If the operation succeeds, the stack
                    187:  * pointer is reset to point to the result. If the routine fails, control
                    188:  * transfers to efail.
                    189:  */
                    190: #define Call_Cond(n) if ((*(optab[op]))(rargp) == A_Failure) \
                    191:          goto efail; \
                    192:          else \
                    193:          rsp = (word *) rargp + 1;
                    194: 
                    195: /*
                    196:  * Call_Gen(n) - Call a generator. A C routine associated with the
                    197:  *  current opcode is called. When it when it terminates, control is 
                    198:  *  passed to C_rtn_term to deal with the termination condition appropriately.
                    199:  */
                    200: #define Call_Gen(n)   signal = (*(optab[op]))(rargp); \
                    201:          goto C_rtn_term;
                    202: 
                    203: /*
                    204:  * GetWord fetches the next icode word.  PutWord(x) stores x at the current
                    205:  * icode word.
                    206:  */
                    207: #define GetWord (*ipc++)
                    208: #define PutWord(x) ipc[-1] = (x)
                    209: /*
                    210:  * DerefArg(n) dereferences the n'th argument.
                    211:  */
                    212: #define DerefArg(n)   DeRef(rargp[n])
                    213: 
                    214: /*
                    215:  * For the sake of efficiency, the stack pointer is kept in a register
                    216:  *  variable, rsp, in the interpreter loop.  Since this variable is
                    217:  *  only accessible inside the loop, and the global variable sp is used
                    218:  *  for the stack pointer elsewhere, rsp must be stored into sp when
                    219:  *  the context of the loop is left and conversely, rsp must be loaded
                    220:  *  from sp when the loop is reentered.  The macros ExInterp and EntInterp,
                    221:  *  respectively, handle these operations.  Currently, this register/global
                    222:  *  scheme is only used for the stack pointer, but it can be easily extended
                    223:  *  to other variables.
                    224:  */
                    225: 
                    226: #define ExInterp   sp = rsp;
                    227: #define EntInterp   rsp = sp;
                    228: 
                    229: /*
                    230:  * Inside the interpreter loop, PushDesc, PushNull, and
                    231:  *  PushVal use rsp instead of sp for efficiency.
                    232:  */
                    233: 
                    234: #undef PushDesc
                    235: #undef PushNull
                    236: #undef PushVal
                    237: #undef PushAVal
                    238: #define PushDesc(d)   {rsp++;*rsp=((d).dword);rsp++;*rsp=((d).vword.integr);}
                    239: #define PushNull   {rsp++; *rsp = D_Null; rsp++; *rsp = 0;}
                    240: #define PushVal(v)   {rsp++; *rsp = (word)(v);}
                    241: #ifdef MSDOS
                    242: #ifdef LPTR
                    243: #define PushAVal(v) {rsp++; \
                    244:                        stkword.stkadr = (char *)(v); \
                    245:                        *rsp = stkword.stkint; \
                    246:                        }
                    247: #else LPTR
                    248: #define PushAVal PushVal
                    249: #endif LPTR
                    250: #else MSDOS
                    251: #define PushAVal PushVal
                    252: #endif MSDOS
                    253: 
                    254: /*
                    255:  * The main loop of the interpreter.
                    256:  */
                    257: 
                    258: interp(fsig,cargp)
                    259: int fsig;
                    260: struct descrip *cargp;
                    261:    {
                    262:    register word opnd, op;
                    263:    register word *rsp;
                    264:    register struct descrip *rargp;
                    265:    register struct ef_marker *newefp;
                    266:    register struct gf_marker *newgfp;
                    267:    register word *wd;
                    268:    register word *firstwd, *lastwd;
                    269:    word *oldsp;
                    270:    int type, signal;
                    271:    extern int (*optab[])();
                    272:    extern char *ident;
                    273:    extern word tallybin[];
                    274: 
                    275:    ilevel++;
                    276: #if (Instr % Instr_level) == 0
                    277:    if (ilevel > maxilevel)
                    278:       maxilevel = ilevel;
                    279: #endif Instr
                    280:    EntInterp;
                    281:    if (fsig == G_Csusp) {
                    282:       oldsp = rsp;
                    283:    
                    284:       /*
                    285:        * Create the generator frame.
                    286:        */
                    287:       newgfp = (struct gf_marker *)(rsp + 1);
                    288:       newgfp->gf_gentype = G_Csusp;
                    289:       newgfp->gf_gfp = gfp;
                    290:       newgfp->gf_efp = efp;
                    291:       newgfp->gf_ipc = ipc;
                    292:       newgfp->gf_line = line;
                    293:       rsp += Wsizeof(struct gf_smallmarker);
                    294:    
                    295:       /*
                    296:        * Region extends from first word after the marker for the generator
                    297:        *  or expression frame enclosing the call to the now-suspending
                    298:        *  routine to the first argument of the routine.
                    299:        */
                    300:       if (gfp != 0) {
                    301:          if (gfp->gf_gentype == G_Psusp)
                    302:             firstwd = (word *)gfp + Wsizeof(*gfp);
                    303:          else
                    304:             firstwd = (word *)gfp + Wsizeof(struct gf_smallmarker);
                    305:          }
                    306:       else
                    307:          firstwd = (word *)efp + Wsizeof(*efp);
                    308:       lastwd = (word *)cargp + 1;
                    309: 
                    310:       /*
                    311:        * Copy the portion of the stack with endpoints firstwd and lastwd
                    312:        *  (inclusive) to the top of the stack.
                    313:        */
                    314:       for (wd = firstwd; wd <= lastwd; wd++)
                    315:          *++rsp = *wd;
                    316:       gfp = newgfp;
                    317:       }
                    318:    for (;;) {                  /* Top of the interpreter loop */
                    319: #if (Instr % Instr_level) == 0
                    320:       if (sp > maxsp)
                    321:          maxsp = sp;
                    322: #endif Instr
                    323:       op = GetWord;            /* Instruction fetch */
                    324: 
                    325:       switch (op) {            /*
                    326:                                 * Switch on opcode.  The cases are
                    327:                                 * organized roughly by functionality
                    328:                                 * to make it easier to find things.
                    329:                                 * For some C compilers, there may be
                    330:                                 * an advantage to arranging them by
                    331:                                 * likelihood of selection.
                    332:                                 */
                    333: 
                    334:                                /* ---Constant construction--- */
                    335: 
                    336:          case Op_Cset:         /* cset */
                    337:             PutWord(Op_Acset);
                    338:             PushVal(D_Cset);
                    339:             opnd = GetWord;
                    340:             opnd += (word)ipc;
                    341:             PutWord(opnd);
                    342:             PushAVal(opnd);
                    343:             break;
                    344: 
                    345:          case Op_Acset:                /* cset, absolute address */
                    346:             PushVal(D_Cset);
                    347:             PushAVal(GetWord);
                    348:             break;
                    349: 
                    350: 
                    351: /* >int */
                    352:          case Op_Int:          /* integer */
                    353:             PushVal(D_Integer);
                    354:             PushVal(GetWord);
                    355:             break;
                    356: /* <int */
                    357: 
                    358: #if IntSize == 16
                    359:          case Op_Long:         /* long integer */
                    360:             PutWord(Op_Along);
                    361:             PushVal(D_Longint);
                    362:             opnd = GetWord;
                    363:             opnd += (word)(ipc);
                    364:             PutWord(opnd);
                    365:             PushAVal(opnd);
                    366:             break;
                    367: 
                    368:          case Op_Along:                /* long integer, absolute address */
                    369:             PushVal(D_Longint);
                    370:             PushAVal(GetWord);
                    371:             break;
                    372: #endif IntSize == 16
                    373: 
                    374:          case Op_Real:         /* real */
                    375:             PutWord(Op_Areal);
                    376:             PushVal(D_Real);
                    377:             opnd = GetWord;
                    378:             opnd += (word)ipc;
                    379:             PushAVal(opnd);
                    380:             PutWord(opnd);
                    381:             break;
                    382: 
                    383:          case Op_Areal:                /* real, absolute address */
                    384:             PushVal(D_Real);
                    385:             PushAVal(GetWord);
                    386:             break;
                    387: 
                    388:          case Op_Str:          /* string */
                    389:             PutWord(Op_Astr);
                    390:             PushVal(GetWord)
                    391:             opnd = (word)ident + GetWord;
                    392:             PutWord(opnd);
                    393:             PushAVal(opnd);
                    394:             break;
                    395: 
                    396:          case Op_Astr:         /* string, absolute address */
                    397:             PushVal(GetWord);
                    398:             PushAVal(GetWord);
                    399:             break;
                    400: 
                    401:                                /* ---Variable construction--- */
                    402: 
                    403:          case Op_Arg:          /* argument */
                    404:             PushVal(D_Var);
                    405:             PushAVal(&argp[GetWord + 1]);
                    406:             break;
                    407: 
                    408:          case Op_Global:       /* global */
                    409:             PutWord(Op_Aglobal);
                    410:             PushVal(D_Var);
                    411:             opnd = GetWord;
                    412:             PushAVal(&globals[opnd]);
                    413:             PutWord((word)&globals[opnd]);
                    414:             break;
                    415: 
                    416:          case Op_Aglobal:      /* global, absolute address */
                    417:             PushVal(D_Var);
                    418:             PushAVal(GetWord);
                    419:             break;
                    420: 
                    421:          case Op_Local:                /* local */
                    422:             PushVal(D_Var);
                    423:             PushAVal(&pfp->pf_locals[GetWord]);
                    424:             break;
                    425: 
                    426:          case Op_Static:       /* static */
                    427:             PutWord(Op_Astatic);
                    428:             PushVal(D_Var);
                    429:             opnd = GetWord;
                    430:             PushAVal(&statics[opnd]);
                    431:             PutWord((word)&statics[opnd]);
                    432:             break;
                    433: 
                    434:          case Op_Astatic:      /* static, absolute address */
                    435:             PushVal(D_Var);
                    436:             PushAVal(GetWord);
                    437:             break;
                    438: 
                    439:                                /* ---Operators--- */
                    440: 
                    441:                                /* Unconditional unary operators */
                    442: 
                    443:          case Op_Compl:                /* ~e */
                    444:          case Op_Neg:          /* -e */
                    445:          case Op_Number:       /* +e */
                    446:          case Op_Refresh:      /* ^e */
                    447:          case Op_Size:         /* *e */
                    448:          case Op_Value:                /* .e */
                    449:             Setup_Op(1);
                    450:             DerefArg(1);
                    451:             Call_Op(1);
                    452:             break;
                    453:                                /* Conditional unary operators */
                    454: 
                    455:          case Op_Nonnull:      /* \e */
                    456:          case Op_Null:         /* /e */
                    457:             Setup_Op(1);
                    458:             Call_Cond(1);
                    459:             break;
                    460: 
                    461:          case Op_Random:       /* ?e */
                    462:             PushNull;
                    463:             Setup_Op(2)
                    464:             Call_Cond(2)
                    465:             break;
                    466: 
                    467:                                /* Generative unary operators */
                    468: 
                    469:          case Op_Tabmat:       /* =e */
                    470:             Setup_Op(1);
                    471:             DerefArg(1);
                    472:             Call_Gen(1);
                    473:             break;
                    474: 
                    475:          case Op_Bang:         /* !e */
                    476:             PushNull;
                    477:             Setup_Op(2);
                    478:             Call_Gen(2);
                    479:             break;
                    480: 
                    481:                                /* Unconditional binary operators */
                    482: 
                    483:          case Op_Cat:          /* e1 || e2 */
                    484:          case Op_Diff:         /* e1 -- e2 */
                    485:          case Op_Div:          /* e1 / e2 */
                    486:          case Op_Inter:                /* e1 ** e2 */
                    487:          case Op_Lconcat:      /* e1 ||| e2 */
                    488:          case Op_Minus:                /* e1 - e2 */
                    489:          case Op_Mod:          /* e1 % e2 */
                    490:          case Op_Mult:         /* e1 * e2 */
                    491:          case Op_Power:                /* e1 ^ e2 */
                    492:          case Op_Unions:       /* e1 ++ e2 */
                    493: /* >plus */
                    494:          case Op_Plus:         /* e1 + e2 */
                    495:             Setup_Op(2);
                    496:             DerefArg(1);
                    497:             DerefArg(2);
                    498:             Call_Op(2);
                    499:             break;
                    500: /* <plus */
                    501:                                /* Conditional binary operators */
                    502: 
                    503:          case Op_Eqv:          /* e1 === e2 */
                    504:          case Op_Lexeq:                /* e1 == e2 */
                    505:          case Op_Lexge:                /* e1 >>= e2 */
                    506:          case Op_Lexgt:                /* e1 >> e2 */
                    507:          case Op_Lexle:                /* e1 <<= e2 */
                    508:          case Op_Lexlt:                /* e1 << e2 */
                    509:          case Op_Lexne:                /* e1 ~== e2 */
                    510:          case Op_Neqv:         /* e1 ~=== e2 */
                    511:          case Op_Numeq:                /* e1 = e2 */
                    512:          case Op_Numge:                /* e1 >= e2 */
                    513:          case Op_Numgt:                /* e1 > e2 */
                    514:          case Op_Numle:                /* e1 <= e2 */
                    515:          case Op_Numne:                /* e1 ~= e2 */
                    516: /* >numlt */
                    517:          case Op_Numlt:                /* e1 < e2 */
                    518:             Setup_Op(2);
                    519:             DerefArg(1);
                    520:             DerefArg(2);
                    521:             Call_Cond(2);
                    522:             break;
                    523: /* <numlt */
                    524: 
                    525:          case Op_Asgn:         /* e1 := e2 */
                    526:             Setup_Op(2);
                    527:             DerefArg(2);
                    528:             Call_Cond(2);
                    529:             break;
                    530: 
                    531:          case Op_Swap:         /* e1 :=: e2 */
                    532:             PushNull;
                    533:             Setup_Op(3);
                    534:             Call_Cond(3);
                    535:             break;
                    536: 
                    537:          case Op_Subsc:                /* e1[e2] */
                    538:             PushNull;
                    539:             Setup_Op(3);
                    540:             DerefArg(2);
                    541:             Call_Cond(3);
                    542:             break;
                    543:                                /* Generative binary operators */ 
                    544: 
                    545:          case Op_Rasgn:                /* e1 <- e2 */
                    546:             Setup_Op(2);
                    547:             DerefArg(2);
                    548:             Call_Gen(2);
                    549:             break;
                    550: 
                    551:          case Op_Rswap:                /* e1 <-> e2 */
                    552:             PushNull;
                    553:             Setup_Op(3);
                    554:             Call_Gen(3);
                    555:             break;
                    556: 
                    557:                                /* Conditional ternary operators */
                    558: 
                    559:          case Op_Sect:         /* e1[e2:e3] */
                    560:             PushNull;
                    561:             Setup_Op(4);
                    562:             DerefArg(2);
                    563:             DerefArg(3);
                    564:             Call_Cond(4);
                    565:             break;
                    566:                                /* Generative ternary operators */ 
                    567: 
                    568:          case Op_Toby:         /* e1 to e2 by e3 */
                    569:             Setup_Op(3);
                    570:             DerefArg(1);
                    571:             DerefArg(2);
                    572:             DerefArg(3);
                    573:             Call_Gen(3);
                    574:             break;
                    575: 
                    576:                                /* ---String Scanning--- */
                    577: 
                    578:          case Op_Bscan:                /* prepare for scanning */
                    579:             PushDesc(k_subject);
                    580:             PushVal(D_Integer);
                    581:             PushVal(k_pos);
                    582:             Setup_Op(0);
                    583:             signal = bscan(0,rargp);
                    584:             goto C_rtn_term;
                    585: 
                    586:          case Op_Escan:                /* exit from scanning */
                    587:             Setup_Op(3);
                    588:             signal = escan(3,rargp);
                    589:             goto C_rtn_term;
                    590: 
                    591:                                /* ---Other Language Operations--- */
                    592: 
                    593:          case Op_Invoke: {     /* invoke */
                    594:             ExInterp;
                    595:             { int nargs;
                    596:               struct descrip *carg;
                    597: 
                    598:             type = invoke((int)GetWord, &carg, &nargs);
                    599:             rargp = carg;
                    600:             EntInterp;
                    601:             if (type == I_Goal_Fail)
                    602:                goto efail;
                    603:             if (type == I_Continue)
                    604:                break;
                    605:             else {
                    606:                int (*bfunc)();
                    607:                struct b_proc *bproc;
                    608: 
                    609:                bproc = (struct b_proc *)BlkLoc(*rargp);
                    610:                bfunc = bproc->entryp.ccode;
                    611: 
                    612:                /* ExInterp -- not needed since no change
                    613:                      since last EntInterp */
                    614:                if (type == I_Vararg)
                    615:                   signal = (*bfunc)(nargs,rargp);
                    616:                else
                    617:                   signal = (*bfunc)(rargp);
                    618:                goto C_rtn_term;
                    619:                }
                    620:             }
                    621:             break;
                    622:             }
                    623: 
                    624:          case Op_Keywd:                /* keyword */
                    625:             PushVal(D_Integer);
                    626:             PushVal(GetWord);
                    627:             Setup_Op(0);
                    628:             signal = keywd(0,rargp);
                    629:             break;
                    630: 
                    631:          case Op_Llist:                /* construct list */
                    632:             opnd = GetWord;
                    633:             Setup_Op(opnd);
                    634:             llist((int)opnd,rargp);
                    635:             rsp = (word *) rargp + 1;
                    636:             break;
                    637: 
                    638:                                /* ---Marking and Unmarking--- */
                    639: 
                    640:          case Op_Mark:         /* create expression frame marker */
                    641:             PutWord(Op_Amark);
                    642:             opnd = GetWord;
                    643:             opnd += (word)ipc;
                    644:             PutWord(opnd);
                    645:             newefp = (struct ef_marker *)(rsp + 1);
                    646:             newefp->ef_failure = (word *)opnd;
                    647:             goto mark;
                    648: 
                    649:          case Op_Amark:                /* mark with absolute fipc */
                    650:             newefp = (struct ef_marker *)(rsp + 1);
                    651:             newefp->ef_failure = (word *)GetWord;
                    652: mark:
                    653:             newefp->ef_gfp = gfp;
                    654:             newefp->ef_efp = efp;
                    655:             newefp->ef_ilevel = ilevel;
                    656:             rsp += Wsizeof(*efp);
                    657:             efp = newefp;
                    658:             gfp = 0;
                    659:             break;
                    660: 
                    661:          case Op_Mark0:                /* create expression frame with 0 ipl */
                    662: mark0:
                    663:             newefp = (struct ef_marker *)(rsp + 1);
                    664:             newefp->ef_failure = 0;
                    665:             newefp->ef_gfp = gfp;
                    666:             newefp->ef_efp = efp;
                    667:             newefp->ef_ilevel = ilevel;
                    668:             rsp += Wsizeof(*efp);
                    669:             efp = newefp;
                    670:             gfp = 0;
                    671:             break;
                    672: 
                    673: /* >unmark */
                    674:          case Op_Unmark:       /* remove expression frame */
                    675:             gfp = efp->ef_gfp;
                    676:             rsp = (word *)efp - 1;
                    677: 
                    678:             /*
                    679:              * Remove any suspended C generators.
                    680:              */
                    681: Unmark_uw:
                    682:             if (efp->ef_ilevel != ilevel) {
                    683:                --ilevel;
                    684:                ExInterp;
                    685:                return A_Unmark_uw;
                    686:                }
                    687:             efp = efp->ef_efp;
                    688:             break;
                    689: /* <unmark */
                    690: 
                    691:                                /* ---Suspensions--- */
                    692: 
                    693:          case Op_Esusp:        {       /* suspend from expression */
                    694: 
                    695:             /*
                    696:              * Create the generator frame.
                    697:              */
                    698:             oldsp = rsp;
                    699:             newgfp = (struct gf_marker *)(rsp + 1);
                    700:             newgfp->gf_gentype = G_Esusp;
                    701:             newgfp->gf_gfp = gfp;
                    702:             newgfp->gf_efp = efp;
                    703:             newgfp->gf_ipc = ipc;
                    704:             newgfp->gf_line = line;
                    705:             gfp = newgfp;
                    706:             rsp += Wsizeof(struct gf_smallmarker);
                    707: 
                    708:             /*
                    709:              * Region extends from first word after enclosing generator or
                    710:              *  expression frame marker to marker for current expression frame.
                    711:              */
                    712:             if (efp->ef_gfp != 0) {
                    713:                newgfp = (struct gf_marker *)(efp->ef_gfp);
                    714:                if (newgfp->gf_gentype == G_Psusp)
                    715:                   firstwd = (word *)efp->ef_gfp + Wsizeof(*gfp);
                    716:                else
                    717:                   firstwd = (word *)efp->ef_gfp + Wsizeof(struct gf_smallmarker);
                    718:                 }
                    719:             else
                    720:                firstwd = (word *)efp->ef_efp + Wsizeof(*efp);
                    721:             lastwd = (word *)efp - 1;
                    722:             efp = efp->ef_efp;
                    723: 
                    724:             /*
                    725:              * Copy the portion of the stack with endpoints firstwd and lastwd
                    726:              *  (inclusive) to the top of the stack.
                    727:              */
                    728:             for (wd = firstwd; wd <= lastwd; wd++)
                    729:                *++rsp = *wd;
                    730:             PushVal(oldsp[-1]);
                    731:             PushVal(oldsp[0]);
                    732:             break;
                    733:             }
                    734: 
                    735:          case Op_Lsusp: {      /* suspend from limitation */
                    736:             struct descrip sval;
                    737: 
                    738:             /*
                    739:              * The limit counter is contained in the descriptor immediately
                    740:              *  prior to the current expression frame.  lval is established
                    741:              *  as a pointer to this descriptor.
                    742:              */
                    743:             struct descrip *lval = (struct descrip *)((word *)efp - 2);
                    744: 
                    745:             /*
                    746:              * Decrement the limit counter and check it.
                    747:              */
                    748:             if (--IntVal(*lval) != 0) {
                    749:                /*
                    750:                 * The limit has not been reached, set up stack.
                    751:                 */
                    752: 
                    753:                sval = *(struct descrip *)(rsp - 1);    /* save result */
                    754: 
                    755:                /*
                    756:                 * Region extends from first word after enclosing generator or
                    757:                 *  expression frame marker to the limit counter just prior to
                    758:                 *  to the current expression frame marker.
                    759:                 */
                    760:                if (efp->ef_gfp != 0) {
                    761:                   newgfp = (struct gf_marker *)(efp->ef_gfp);
                    762:                   if (newgfp->gf_gentype == G_Psusp)
                    763:                      firstwd = (word *)efp->ef_gfp + Wsizeof(*gfp);
                    764:                   else
                    765:                      firstwd = (word *)efp->ef_gfp + Wsizeof(struct gf_smallmarker);
                    766:                   }
                    767:                else
                    768:                   firstwd = (word *)efp->ef_efp + Wsizeof(*efp);
                    769:                lastwd = (word *)efp - 3;
                    770:                efp = efp->ef_efp;
                    771: 
                    772:                /*
                    773:                 * Copy the portion of the stack with endpoints firstwd and lastwd
                    774:                 *  (inclusive) to the top of the stack.
                    775:                 */
                    776:                rsp -= 2;               /* overwrite result */
                    777:                for (wd = firstwd; wd <= lastwd; wd++)
                    778:                   *++rsp = *wd;
                    779:                PushDesc(sval);         /* push saved result */
                    780:                }
                    781:             else {
                    782:                /*
                    783:                 * Otherwise, the limit has been reached.  Instead of
                    784:                 *  suspending, remove the current expression frame and
                    785:                 *  replace the limit counter with the value on top of
                    786:                 *  the stack (which would have been suspended had the
                    787:                 *  limit not been reached).
                    788:                 */
                    789:                *lval = *(struct descrip *)(rsp - 1);
                    790:                gfp = efp->ef_gfp;
                    791: 
                    792:                /*
                    793:                 * Since an expression frame is being removed, inactive
                    794:                 *  C generators contained therein are deactivated.
                    795:                 */
                    796: Lsusp_uw:
                    797:                if (efp->ef_ilevel != ilevel) {
                    798:                   --ilevel;
                    799:                   ExInterp;
                    800:                   return A_Lsusp_uw;
                    801:                   }
                    802:                rsp = (word *)efp - 1;
                    803:                efp = efp->ef_efp;
                    804:                }
                    805:             break;
                    806:             }
                    807: 
                    808:          case Op_Psusp: {      /* suspend from procedure */
                    809:             /*
                    810:              * An Icon procedure is suspending a value.  Determine if the
                    811:              *  value being suspended should be dereferenced and if so,
                    812:              *  dereference it. If tracing is on, strace is called
                    813:              * to generate a message.  Appropriate values are
                    814:              *  restored from the procedure frame of the suspending procedure.
                    815:              */
                    816: 
                    817:             struct descrip sval, *svalp;
                    818:             struct b_proc *sproc;
                    819: 
                    820:             svalp = (struct descrip *)(rsp - 1);
                    821:             sval = *svalp;
                    822:             if (Var(sval)) {
                    823:                word *loc;
                    824: 
                    825:                if (Tvar(sval)) {
                    826:                   if (sval.dword == D_Tvsubs) {
                    827:                       struct b_tvsubs *tvb;
                    828: 
                    829:                      tvb = (struct b_tvsubs *)BlkLoc(sval);
                    830:                      loc = (word *)BlkLoc(tvb->ssvar);
                    831:                      }
                    832:                   else
                    833:                      goto ps_noderef;
                    834:                   }
                    835:                else
                    836:                   loc = (word *)BlkLoc(sval);
                    837:                if (loc >= (word *)BlkLoc(current) && loc <= rsp)
                    838:                   deref(svalp);
                    839:                }
                    840: ps_noderef:
                    841: 
                    842:             /*
                    843:              * Create the generator frame.
                    844:              */
                    845:             oldsp = rsp;
                    846:             newgfp = (struct gf_marker *)(rsp + 1);
                    847:             newgfp->gf_gentype = G_Psusp;
                    848:             newgfp->gf_gfp = gfp;
                    849:             newgfp->gf_efp = efp;
                    850:             newgfp->gf_ipc = ipc;
                    851:             newgfp->gf_line = line;
                    852:             newgfp->gf_argp = argp;
                    853:             newgfp->gf_pfp = pfp;
                    854:             gfp = newgfp;
                    855:             rsp += Wsizeof(*gfp);
                    856: 
                    857:             /*
                    858:              * Region extends from first word after the marker for the generator
                    859:              *  or expression frame enclosing the call to the now-suspending
                    860:              *  procedure to Arg0 of the procedure.
                    861:              */
                    862:             if (pfp->pf_gfp != 0) {
                    863:                newgfp = (struct gf_marker *)(pfp->pf_gfp);
                    864:                if (newgfp->gf_gentype == G_Psusp)
                    865:                   firstwd = (word *)pfp->pf_gfp + Wsizeof(*gfp);
                    866:                else
                    867:                   firstwd = (word *)pfp->pf_gfp + Wsizeof(struct gf_smallmarker);
                    868:                }
                    869:             else
                    870:                firstwd = (word *)pfp->pf_efp + Wsizeof(*efp);
                    871:             lastwd = (word *)argp - 1;
                    872:                efp = efp->ef_efp;
                    873: 
                    874:             /*
                    875:              * Copy the portion of the stack with endpoints firstwd and lastwd
                    876:              *  (inclusive) to the top of the stack.
                    877:              */
                    878:             for (wd = firstwd; wd <= lastwd; wd++)
                    879:                *++rsp = *wd;
                    880:             PushVal(oldsp[-1]);
                    881:             PushVal(oldsp[0]);
                    882:             --k_level;
                    883:             if (k_trace) {
                    884:                sproc = (struct b_proc *)BlkLoc(*argp);
                    885:                strace(sproc, svalp);
                    886:                }
                    887:             line = pfp->pf_line;
                    888:             efp = pfp->pf_efp;
                    889:             ipc = pfp->pf_ipc;
                    890:             argp = pfp->pf_argp;
                    891:             pfp = pfp->pf_pfp;
                    892:             break;
                    893:             }
                    894: 
                    895:                                /* ---Returns--- */
                    896: 
                    897:          case Op_Eret: {       /* return from expression */
                    898:             /*
                    899:              * Op_Eret removes the current expression frame, leaving the
                    900:              *  original top of stack value on top.
                    901:              */
                    902:             /*
                    903:              * Save current top of stack value in global temporary (no
                    904:              *  danger of reentry).
                    905:              */
                    906:             eret_tmp = *(struct descrip *)&rsp[-1];
                    907:             gfp = efp->ef_gfp;
                    908: Eret_uw:
                    909:             /*
                    910:              * Since an expression frame is being removed, inactive
                    911:              *  C generators contained therein are deactivated.
                    912:              */
                    913:             if (efp->ef_ilevel != ilevel) {
                    914:                --ilevel;
                    915:                ExInterp;
                    916:                return A_Eret_uw;
                    917:                }
                    918:             rsp = (word *)efp - 1;
                    919:             efp = efp->ef_efp;
                    920:             PushDesc(eret_tmp);
                    921:             break;
                    922:             }
                    923: 
                    924:          case Op_Pret: {       /* return from procedure */
                    925:             /*
                    926:              * An Icon procedure is returning a value.  Determine if the
                    927:              *  value being returned should be dereferenced and if so,
                    928:              *  dereference it.  If tracing is on, rtrace is called to
                    929:              *  generate a message.  Inactive generators created after
                    930:              *  the activation of the procedure are deactivated.  Appropriate
                    931:              *  values are restored from the procedure frame.
                    932:              */
                    933:             struct descrip rval;
                    934:             struct b_proc *rproc = (struct b_proc *)BlkLoc(*argp);
                    935: 
                    936:             *argp = *(struct descrip *)(rsp - 1);
                    937:             rval = *argp;
                    938:             if (Var(rval)) {
                    939:                word *loc;
                    940: 
                    941:                if (Tvar(rval)) {
                    942:                   if (rval.dword == D_Tvsubs) {
                    943:                       struct b_tvsubs *tvb;
                    944: 
                    945:                      tvb = (struct b_tvsubs *)BlkLoc(rval);
                    946:                      loc = (word *)BlkLoc(tvb->ssvar);
                    947:                      }
                    948:                   else
                    949:                      goto pr_noderef;
                    950:                   }
                    951:                else
                    952:                   loc = (word *)BlkLoc(rval);
                    953:                if (loc >= (word *)BlkLoc(current) && loc <= rsp)
                    954:                   deref(argp);
                    955:                }
                    956: 
                    957: pr_noderef:
                    958:             --k_level;
                    959:             if (k_trace)
                    960:                rtrace(rproc, argp);
                    961: Pret_uw:
                    962:             if (pfp->pf_ilevel != ilevel) {
                    963:                --ilevel;
                    964:                ExInterp;
                    965:                return A_Pret_uw;
                    966:                }
                    967:             rsp = (word *)argp + 1;
                    968:             line = pfp->pf_line;
                    969:             efp = pfp->pf_efp;
                    970:             gfp = pfp->pf_gfp;
                    971:             ipc = pfp->pf_ipc;
                    972:             argp = pfp->pf_argp;
                    973:             pfp = pfp->pf_pfp;
                    974:             break;
                    975:             }
                    976: 
                    977:                                /* ---Failures--- */
                    978: 
                    979: /* >efail1 */
                    980:          case Op_Efail:
                    981: efail:
                    982:             /*
                    983:              * Failure has occurred in the current expression frame.
                    984:              */
                    985:             if (gfp == 0) {
                    986:                /*
                    987:                 * There are no inactive generators to resume.  Remove
                    988:                 *  the current expression frame, restoring values.
                    989:                 *
                    990:                 * If the failure address is 0, propagate failure to the
                    991:                 *  enclosing frame by branching back to efail.
                    992:                 */
                    993:                ipc = efp->ef_failure;
                    994:                gfp = efp->ef_gfp;
                    995:                rsp = (word *)efp - 1;
                    996:                efp = efp->ef_efp;
                    997:                if (ipc == 0)
                    998:                   goto efail;
                    999:                break;
                   1000:                }
                   1001: 
                   1002:             else {
                   1003:                /*
                   1004:                 * There is a generator that can be resumed.  Make
                   1005:                 *  the stack adjustments and then switch on the 
                   1006:                 *  type of the generator frame marker.
                   1007:                 */
                   1008:                register struct gf_marker *resgfp = gfp;
                   1009: 
                   1010:                type = resgfp->gf_gentype;
                   1011: /* <efail1 */
                   1012:                if (type == G_Psusp) {
                   1013:                   argp = resgfp->gf_argp;
                   1014:                   if (k_trace) {       /* procedure tracing */
                   1015:                      ExInterp;
                   1016:                      atrace(BlkLoc(*argp));
                   1017:                      EntInterp;
                   1018:                      }
                   1019:                   }
                   1020: /* >efail2 */
                   1021:                ipc = resgfp->gf_ipc;
                   1022:                efp = resgfp->gf_efp;
                   1023:                line = resgfp->gf_line;
                   1024:                gfp = resgfp->gf_gfp;
                   1025:                rsp = (word *)resgfp - 1;
                   1026: /* <efail2 */
                   1027:                if (type == G_Psusp) {
                   1028:                   pfp = resgfp->gf_pfp;
                   1029:                   ++k_level;           /* adjust procedure level */
                   1030:                   }
                   1031: 
                   1032: /* >efail3 */
                   1033:                switch (type) {
                   1034: 
                   1035:                   case G_Csusp: {
                   1036:                      --ilevel;
                   1037:                      ExInterp;
                   1038:                      return A_Resumption;
                   1039:                      break;
                   1040:                      }
                   1041: 
                   1042:                   case G_Esusp:
                   1043:                      goto efail;
                   1044: 
                   1045:                   case G_Psusp:
                   1046:                      break;
                   1047:                   }
                   1048: 
                   1049:                break;
                   1050:                }
                   1051: /* <efail3 */
                   1052: 
                   1053:          case Op_Pfail:                /* fail from procedure */
                   1054:             /*
                   1055:              * An Icon procedure is failing.  Generate tracing message if
                   1056:              *  tracing is on.  Deactivate inactive C generators created
                   1057:              *  after activation of the procedure.  Appropriate values
                   1058:              *  are restored from the procedure frame.
                   1059:              */
                   1060:             --k_level;
                   1061:             if (k_trace)
                   1062:                ftrace(BlkLoc(*argp));
                   1063: Pfail_uw:
                   1064:             if (pfp->pf_ilevel != ilevel) {
                   1065:                --ilevel;
                   1066:                ExInterp;
                   1067:                return A_Pfail_uw;
                   1068:                }
                   1069:             line = pfp->pf_line;
                   1070:             efp = pfp->pf_efp;
                   1071:             gfp = pfp->pf_gfp;
                   1072:             ipc = pfp->pf_ipc;
                   1073:             argp = pfp->pf_argp;
                   1074:             pfp = pfp->pf_pfp;
                   1075:             goto efail;
                   1076: 
                   1077:                                /* ---Odds and Ends--- */
                   1078: 
                   1079:          case Op_Ccase:                /* case clause */
                   1080:             PushNull;
                   1081:             PushVal(((word *)efp)[-2]);
                   1082:             PushVal(((word *)efp)[-1]);
                   1083:             break;
                   1084: 
                   1085:          case Op_Chfail:       /* change failure ipc */
                   1086:             opnd = GetWord;
                   1087:             opnd += (word)ipc;
                   1088:             efp->ef_failure = (word *)opnd;
                   1089:             break;
                   1090: 
                   1091:          case Op_Dup:          /* duplicate descriptor */
                   1092:             PushNull;
                   1093:             rsp[1] = rsp[-3];
                   1094:             rsp[2] = rsp[-2];
                   1095:             rsp += 2;
                   1096:             break;
                   1097: 
                   1098:          case Op_Field:                /* e1.e2 */
                   1099:             PushVal(D_Integer);
                   1100:             PushVal(GetWord);
                   1101:             Setup_Op(2);
                   1102:             signal = field(2,rargp);
                   1103:             goto C_rtn_term;
                   1104: 
                   1105:          case Op_Goto:          /* goto */
                   1106:             PutWord(Op_Agoto);
                   1107:             opnd = GetWord;
                   1108:             opnd += (word)ipc;
                   1109:             PutWord(opnd);
                   1110:             ipc = (word *)opnd;
                   1111:             break;
                   1112: 
                   1113:          case Op_Agoto:         /* goto absolute address */
                   1114:             opnd = GetWord;
                   1115:             ipc = (word *)opnd;
                   1116:             break;
                   1117: 
                   1118:          case Op_Init:         /* initial */
                   1119:             *--ipc = Op_Goto;
                   1120:             opnd = sizeof(*ipc) + sizeof(*rsp);
                   1121:             opnd += (word)ipc;
                   1122:             ipc = (word *)opnd;
                   1123:             break;
                   1124: 
                   1125:          case Op_Limit:                /* limit */
                   1126:             Setup_Op(0);
                   1127:             if (limit(0,rargp) == A_Failure)
                   1128:                goto efail;
                   1129:             else
                   1130:                rsp = (word *) rargp + 1;
                   1131:             goto mark0;
                   1132: 
                   1133:          case Op_Line:         /* line */
                   1134:             line = GetWord;
                   1135:             break;
                   1136: 
                   1137:          case Op_Tally:                /* tally */
                   1138:             tallybin[GetWord]++;
                   1139:             break;
                   1140: 
                   1141:          case Op_Pnull:                /* push null descriptor */
                   1142:             PushNull;
                   1143:             break;
                   1144: 
                   1145:          case Op_Pop:          /* pop descriptor */
                   1146:             rsp -= 2;
                   1147:             break;
                   1148: 
                   1149:          case Op_Push1:                /* push integer 1 */
                   1150:             PushVal(D_Integer);
                   1151:             PushVal(1);
                   1152:             break;
                   1153: 
                   1154:          case Op_Pushn1:       /* push integer -1 */
                   1155:             PushVal(D_Integer);
                   1156:             PushVal(-1);
                   1157:             break;
                   1158: 
                   1159:          case Op_Sdup:         /* duplicate descriptor */
                   1160:             rsp += 2;
                   1161:             rsp[-1] = rsp[-3];
                   1162:             rsp[0] = rsp[-2];
                   1163:             break;
                   1164: 
                   1165:                                        /* ---Co-expressions--- */
                   1166: 
                   1167:          case Op_Create:       /* create */
                   1168:            PushNull;
                   1169:             Setup_Op(0);
                   1170:             opnd = GetWord;
                   1171:             opnd += (word)ipc;
                   1172:             signal = create((word *)opnd, rargp);
                   1173:             goto C_rtn_term;
                   1174: 
                   1175: 
                   1176:         case Op_Coact: {       /* @e */
                   1177:            register struct b_coexpr *ccp, *ncp;
                   1178:            struct descrip *dp, *tvalp;
                   1179:             word first;
                   1180:            
                   1181:            ExInterp;
                   1182:            dp = (struct descrip *)(sp - 1);
                   1183:            DeRef(*dp);
                   1184:            if (dp->dword != D_Coexpr)
                   1185:               runerr(118, dp);
                   1186:            ccp = (struct b_coexpr *)BlkLoc(current);
                   1187:            ncp = (struct b_coexpr *)BlkLoc(*dp);
                   1188:             if (ncp->tvalloc != NULL)          /* Cannot activate co-expression */
                   1189:                runerr(214, NULL);              /*  that is already active */
                   1190:            /*
                   1191:             * Save Istate of current co-expression.
                   1192:             */
                   1193:            ccp->es_pfp = pfp;
                   1194:            ccp->es_argp = argp;
                   1195:            ccp->es_efp = efp;
                   1196:            ccp->es_gfp = gfp;
                   1197:            ccp->es_ipc = ipc;
                   1198:            ccp->es_sp = sp;
                   1199:            ccp->es_ilevel = ilevel;
                   1200:            ccp->es_line = line;
                   1201:            ccp->tvalloc = (struct descrip *)(sp - 3);
                   1202:            /*
                   1203:             * Establish Istate for new co-expression.
                   1204:             */
                   1205:            pfp = ncp->es_pfp;
                   1206:            argp = ncp->es_argp;
                   1207:            efp = ncp->es_efp;
                   1208:            gfp = ncp->es_gfp;
                   1209:            ipc = ncp->es_ipc;
                   1210:            sp = ncp->es_sp;
                   1211:            ilevel = ncp->es_ilevel;
                   1212:            line = ncp->es_line;
                   1213: 
                   1214:             if (tvalp = ncp->tvalloc) {
                   1215:               ncp->tvalloc = NULL;
                   1216:               *tvalp = *(struct descrip *)(&ccp->es_sp[-3]);
                   1217:                if (Var(*tvalp)) {
                   1218:                   word *loc;
                   1219:             
                   1220:                   if (Tvar(*tvalp)) {
                   1221:                      if (tvalp->dword == D_Tvsubs) {
                   1222:                         struct b_tvsubs *tvb;
                   1223:                
                   1224:                         tvb = (struct b_tvsubs *)BlkLoc(*tvalp);
                   1225:                         loc = (word *)BlkLoc(tvb->ssvar);
                   1226:                         }
                   1227:                      else
                   1228:                         goto ca_noderef;
                   1229:                      }
                   1230:                   else
                   1231:                      loc = (word *)BlkLoc(*tvalp);
                   1232:                   if (loc >= (word *)ccp && loc <= ccp->es_sp)
                   1233:                      deref(tvalp);
                   1234:                   }
                   1235:               }
                   1236: ca_noderef:
                   1237:            /*
                   1238:             * Set activator in new co-expression.
                   1239:             */
                   1240:             if (ncp->activator.dword == D_Null)
                   1241:                first = 0;
                   1242:             else
                   1243:                first = 1;
                   1244:            ncp->activator.dword = D_Coexpr;
                   1245:            BlkLoc(ncp->activator) = (union block *)ccp;
                   1246:            BlkLoc(current) = (union block *)ncp;
                   1247:            coexp_act = A_Coact;
                   1248:            coswitch(ccp->cstate,ncp->cstate,first);
                   1249:            EntInterp;
                   1250:            if (coexp_act == A_Cofail)
                   1251:               goto efail;
                   1252:            else
                   1253:               rsp -= 2;
                   1254:            break;
                   1255:            }
                   1256:            
                   1257:          case Op_Coret: {      /* return from co-expression */
                   1258:            register struct b_coexpr *ccp, *ncp;
                   1259:            struct descrip *rvalp;
                   1260:            
                   1261:            ExInterp;
                   1262:            ccp = (struct b_coexpr *)BlkLoc(current);
                   1263:            ccp->size++;
                   1264:            ncp = (struct b_coexpr *)BlkLoc(ccp->activator);
                   1265:            ncp->tvalloc = NULL;
                   1266:            rvalp = (struct descrip *)(&ncp->es_sp[-3]);
                   1267:            *rvalp = *(struct descrip *)&sp[-1];
                   1268:             if (Var(*rvalp)) {
                   1269:                word *loc;
                   1270:             
                   1271:                if (Tvar(*rvalp)) {
                   1272:                   if (rvalp->dword == D_Tvsubs) {
                   1273:                       struct b_tvsubs *tvb;
                   1274:                
                   1275:                      tvb = (struct b_tvsubs *)BlkLoc(*rvalp);
                   1276:                      loc = (word *)BlkLoc(tvb->ssvar);
                   1277:                      }
                   1278:                   else
                   1279:                      goto cr_noderef;
                   1280:                   }
                   1281:                else
                   1282:                   loc = (word *)BlkLoc(*rvalp);
                   1283:                if (loc >= (word *)ccp && loc <= sp)
                   1284:                   deref(rvalp);
                   1285:                }
                   1286: cr_noderef:
                   1287:            /*
                   1288:             * Save Istate of current co-expression.
                   1289:             */
                   1290:            ccp->es_pfp = pfp;
                   1291:            ccp->es_argp = argp;
                   1292:            ccp->es_efp = efp;
                   1293:            ccp->es_gfp = gfp;
                   1294:            ccp->es_ipc = ipc;
                   1295:            ccp->es_sp = sp;
                   1296:            ccp->es_ilevel = ilevel;
                   1297:            ccp->es_line = line;
                   1298:            /*
                   1299:             * Establish Istate for new co-expression.
                   1300:             */
                   1301:            pfp = ncp->es_pfp;
                   1302:            argp = ncp->es_argp;
                   1303:            efp = ncp->es_efp;
                   1304:            gfp = ncp->es_gfp;
                   1305:            ipc = ncp->es_ipc;
                   1306:            sp = ncp->es_sp;
                   1307:            ilevel = ncp->es_ilevel;
                   1308:            line = ncp->es_line;
                   1309:            BlkLoc(current) = (union block *)ncp;
                   1310:            coexp_act = A_Coret;
                   1311:            coswitch(ccp->cstate, ncp->cstate,(word)1);
                   1312:            break;
                   1313:            }
                   1314: 
                   1315:          case Op_Cofail: {     /* fail from co-expression */
                   1316:            register struct b_coexpr *ccp, *ncp;
                   1317:            
                   1318:            ExInterp;
                   1319:            ccp = (struct b_coexpr *)BlkLoc(current);
                   1320:            ncp = (struct b_coexpr *)BlkLoc(ccp->activator);
                   1321:            ncp->tvalloc = NULL;
                   1322:            /*
                   1323:             * Save Istate of current co-expression.
                   1324:             */
                   1325:            ccp->es_pfp = pfp;
                   1326:            ccp->es_argp = argp;
                   1327:            ccp->es_efp = efp;
                   1328:            ccp->es_gfp = gfp;
                   1329:            ccp->es_ipc = ipc;
                   1330:            ccp->es_sp = sp;
                   1331:            ccp->es_ilevel = ilevel;
                   1332:            ccp->es_line = line;
                   1333:            /*
                   1334:             * Establish Istate for new co-expression.
                   1335:             */
                   1336:            pfp = ncp->es_pfp;
                   1337:            argp = ncp->es_argp;
                   1338:            efp = ncp->es_efp;
                   1339:            gfp = ncp->es_gfp;
                   1340:            ipc = ncp->es_ipc;
                   1341:            sp = ncp->es_sp;
                   1342:            ilevel = ncp->es_ilevel;
                   1343:            line = ncp->es_line;
                   1344:            BlkLoc(current) = (union block *)ncp;
                   1345:            coexp_act = A_Cofail;
                   1346:            coswitch(ccp->cstate, ncp->cstate,(word)1);
                   1347:            break;
                   1348:            }
                   1349: 
                   1350:          case Op_Quit:         /* quit */
                   1351:             goto interp_quit;
                   1352: 
                   1353:          default: {
                   1354:             char buf[50];
                   1355: 
                   1356:             sprintf(buf, "unimplemented opcode: %ld\n",(long)op);
                   1357:             syserr(buf);
                   1358:             }
                   1359:          }
                   1360:          continue;
                   1361: 
                   1362: /* >crtn */
                   1363: C_rtn_term:
                   1364:          EntInterp;
                   1365:          switch (signal) {
                   1366: 
                   1367:             case A_Failure:
                   1368:                goto efail;
                   1369: 
                   1370:             case A_Unmark_uw:          /* unwind for unmark */
                   1371:                goto Unmark_uw;
                   1372: 
                   1373:             case A_Lsusp_uw:           /* unwind for lsusp */
                   1374:                goto Lsusp_uw;
                   1375: 
                   1376:             case A_Eret_uw:            /* unwind for eret */
                   1377:                goto Eret_uw;
                   1378: 
                   1379:             case A_Pret_uw:            /* unwind for pret */
                   1380:                goto Pret_uw;
                   1381: 
                   1382:             case A_Pfail_uw:           /* unwind for pfail */
                   1383:                goto Pfail_uw;
                   1384:             }
                   1385: 
                   1386:          rsp = (word *) rargp + 1;     /* set rsp to result */
                   1387:          continue;
                   1388:          }
                   1389: /* <crtn */
                   1390: 
                   1391: interp_quit:
                   1392:    --ilevel;
                   1393: #if (Instr % Instr_level) == 0
                   1394:    fprintf(stderr,"maximum ilevel = %d\n",maxilevel);
                   1395:    fprintf(stderr,"maximum sp = %d\n",(long)maxsp - (long)stack);
                   1396:    fflush(stderr);
                   1397: #endif Instr
                   1398:    if (ilevel != 0)
                   1399:       syserr("Interpreter termination with inactive generators!");
                   1400:    }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.