|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.