Annotation of researchv10dc/cmd/icon/src/iconx/interp.c, revision 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.