1: #ifndef lint 2: static char *rcsid = 3: "$Header: eval.c,v 1.6 83/09/07 17:54:42 sklower Exp $"; 4: #endif 5: 6: /* -[Thu Aug 18 10:07:22 1983 by jkf]- 7: * eval.c $Locker: $ 8: * evaluator 9: * 10: * (c) copyright 1982, Regents of the University of California 11: */ 12: 13: #include "global.h" 14: #include <signal.h> 15: #include "frame.h" 16: 17: 18: 19: /* 20: * eval 21: * returns the value of the pointer passed as the argument. 22: * 23: */ 24: 25: lispval 26: eval(actarg) 27: lispval actarg; 28: { 29: #define argptr handy 30: register lispval a = actarg; 31: register lispval handy; 32: register struct nament *namptr; 33: register struct argent *workp; 34: struct nament *oldbnp = bnp; 35: int dopopframe = FALSE; 36: int type, shortcircuit = TRUE; 37: lispval Ifcall(), Iarray(); 38: Savestack(4); 39: 40: /*debugging 41: if (rsetsw && rsetatom->a.clb != nil) { 42: printf("Eval:"); 43: printr(a,stdout); 44: printf("\nrsetsw: %d evalhsw: %d\n", rsetsw, evalhsw); 45: printf("*rset: "); 46: printr(rsetatom->a.clb,stdout); 47: printf(" evalhook: "); 48: printr(evalhatom->a.clb,stdout); 49: printf(" evalhook call flag^G: %d\n", evalhcallsw); 50: fflush(stdout); 51: }; 52: */ 53: 54: /* check if an interrupt is pending and handle if so */ 55: if(sigintcnt > 0) sigcall(SIGINT); 56: 57: if (rsetsw && rsetatom->a.clb != nil) /* if (*rset t) has been done */ 58: { 59: pbuf pb; 60: shortcircuit = FALSE; 61: if (evalhsw != nil && evalhatom->a.clb != nil) 62: { 63: /*if (sstatus evalhook t) 64: and evalhook non-nil */ 65: if (!evalhcallsw) 66: /*if we got here after calling evalhook, then 67: evalhcallsw will be TRUE, so we want to skip calling 68: the hook function, permitting one form to be 69: evaluated before the hook fires. 70: */ 71: { 72: /* setup equivalent of (funcall evalhook <arg to eval>) */ 73: (np++)->val = a; /* push form on namestack */ 74: lbot=np; /* set up args to funcall */ 75: (np++)->val = evalhatom->a.clb; /* push evalhook's clb */ 76: (np++)->val = a; /* eval's arg becomes 77: 2nd arg to funcall */ 78: PUSHDOWN(evalhatom, nil); /* bind evalhook to nil*/ 79: PUSHDOWN(funhatom, nil); /* bind funcallhook to nil*/ 80: funhcallsw = TRUE; /* skip any funcall hook */ 81: handy = Lfuncal(); /* now call funcall */ 82: funhcallsw = FALSE; 83: POP; 84: POP; 85: Restorestack(); 86: return(handy); 87: }; 88: } 89: errp = Pushframe(F_EVAL,a,nil); 90: dopopframe = TRUE; /* remember to pop later */ 91: if(retval == C_FRETURN) 92: { 93: Restorestack(); 94: errp = Popframe(); 95: return(lispretval); 96: } 97: }; 98: 99: evalhcallsw = FALSE; /* clear indication that evalhook called */ 100: 101: switch (TYPE(a)) 102: { 103: case ATOM: 104: if (rsetsw && rsetatom->a.clb != nil && bptr_atom->a.clb != nil) { 105: 106: struct nament *bpntr, *eval1bptr; 107: /* Both rsetsw and rsetatom for efficiency*/ 108: /* bptr_atom set by second arg to eval1 */ 109: eval1bptr = (struct nament *) bptr_atom->a.clb->d.cdr; 110: /* eval1bptr is bnp when eval1 was called; 111: if an atom was bound after this, 112: then its clb is valid */ 113: for (bpntr = eval1bptr; bpntr < bnp; bpntr++) 114: if (bpntr->atm==a) { 115: handy = a->a.clb; 116: goto gotatom; 117: }; /* Value saved in first binding of a, 118: if any, after pointer to eval1, 119: is the valid value, else use its clb */ 120: for (bpntr = (struct nament *)bptr_atom->a.clb->d.car; 121: bpntr < eval1bptr; bpntr++) 122: if (bpntr->atm==a) { 123: handy=bpntr->val; 124: goto gotatom; /* Simply no way around goto here */ 125: }; 126: }; 127: handy = a->a.clb; 128: gotatom: 129: if(handy==CNIL) { 130: handy = errorh1(Vermisc,"Unbound Variable:",nil,TRUE,0,a); 131: } 132: if(dopopframe) errp = Popframe(); 133: Restorestack(); 134: return(handy); 135: 136: case VALUE: 137: if(dopopframe) errp = Popframe(); 138: Restorestack(); 139: return(a->l); 140: 141: case DTPR: 142: (np++)->val = a; /* push form on namestack */ 143: lbot = np; /* define beginning of argstack */ 144: /* oldbnp = bnp; redundant - Mitch Marcus */ 145: a = a->d.car; /* function name or lambda-expr */ 146: for(EVER) 147: { 148: switch(TYPE(a)) 149: { 150: case ATOM: 151: /* get function binding */ 152: if(a->a.fnbnd==nil && a->a.clb!=nil) { 153: a=a->a.clb; 154: if(TYPE(a)==ATOM) 155: a=a->a.fnbnd; 156: } else 157: a = a->a.fnbnd; 158: break; 159: case VALUE: 160: a = a->l; /* get value */ 161: break; 162: } 163: 164: vtemp = (CNIL-1); /* sentinel value for error test */ 165: 166: /*funcal:*/ switch (TYPE(a)) 167: { 168: case BCD: /* function */ 169: argptr = actarg->d.cdr; 170: 171: /* decide whether lambda, nlambda or 172: macro and push args onto argstack 173: accordingly. */ 174: 175: if(a->bcd.discipline==nlambda) { 176: (np++)->val = argptr; 177: TNP; 178: } else if(a->bcd.discipline==macro) { 179: (np++)->val = actarg; 180: TNP; 181: } else for(;argptr!=nil; argptr = argptr->d.cdr) { 182: /* short circuit evaluations of ATOM, INT, DOUB 183: * if not in debugging mode 184: */ 185: if(shortcircuit 186: && ((type = TYPE(argptr->d.car)) == ATOM) 187: && (argptr->d.car->a.clb != CNIL)) 188: (np++)->val = argptr->d.car->a.clb; 189: else if(shortcircuit && 190: ((type == INT) || (type == STRNG))) 191: (np++)->val = argptr->d.car; 192: else 193: (np++)->val = eval(argptr->d.car); 194: TNP; 195: } 196: /* go for it */ 197: 198: if(TYPE(a->bcd.discipline)==STRNG) 199: vtemp = Ifcall(a); 200: else 201: vtemp = (*(lispval (*)())(a->bcd.start))(); 202: break; 203: 204: case ARRAY: 205: vtemp = Iarray(a,actarg->d.cdr,TRUE); 206: break; 207: 208: case DTPR: /* push args on argstack according to 209: type */ 210: protect(a); /* save function definition in case function 211: is redefined */ 212: lbot = np; 213: argptr = a->d.car; 214: if (argptr==lambda) { 215: for(argptr = actarg->d.cdr; 216: argptr!=nil; argptr=argptr->d.cdr) { 217: 218: (np++)->val = eval(argptr->d.car); 219: TNP; 220: } 221: } else if (argptr==nlambda) { 222: (np++)->val = actarg->d.cdr; 223: TNP; 224: } else if (argptr==macro) { 225: (np++)->val = actarg; 226: TNP; 227: } else if (argptr==lexpr) { 228: for(argptr = actarg->d.cdr; 229: argptr!=nil; argptr=argptr->d.cdr) { 230: 231: (np++)->val = eval(argptr->d.car); 232: TNP; 233: } 234: handy = newdot(); 235: handy->d.car = (lispval)lbot; 236: handy->d.cdr = (lispval)np; 237: PUSHDOWN(lexpr_atom,handy); 238: lbot = np; 239: (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car); 240: 241: } else break; /* something is wrong - this isn't a proper function */ 242: 243: argptr = (a->d.cdr)->d.car; 244: namptr = bnp; 245: workp = lbot; 246: if(bnp + (np - lbot)> bnplim) 247: binderr(); 248: for(;argptr != (lispval)nil; 249: workp++,argptr = argptr->d.cdr) /* rebind formal names (shallow) */ 250: { 251: if(argptr->d.car==nil) 252: continue; 253: /*if(((namptr)->atm = argptr->d.car)==nil) 254: error("Attempt to lambda bind nil",FALSE);*/ 255: namptr->atm = argptr->d.car; 256: if (workp < np) { 257: namptr->val = namptr->atm->a.clb; 258: namptr->atm->a.clb = workp->val; 259: } else 260: bnp = namptr, 261: error("Too few actual parameters",FALSE); 262: namptr++; 263: } 264: bnp = namptr; 265: if (workp < np) 266: error("Too many actual parameters",FALSE); 267: 268: /* execute body, implied prog allowed */ 269: 270: for (handy = a->d.cdr->d.cdr; 271: handy != nil; 272: handy = handy->d.cdr) { 273: vtemp = eval(handy->d.car); 274: } 275: } 276: if (vtemp != (CNIL-1)) { 277: /* if we get here with a believable value, */ 278: /* we must have executed a function. */ 279: popnames(oldbnp); 280: 281: /* in case some clown trashed t */ 282: 283: tatom->a.clb = (lispval) tatom; 284: if(a->d.car==macro) 285: { 286: if(Vdisplacemacros->a.clb && (TYPE(vtemp) == DTPR)) 287: { 288: actarg->d.car = vtemp->d.car; 289: actarg->d.cdr = vtemp->d.cdr; 290: } 291: vtemp = eval(vtemp); 292: } 293: /* It is of the most wonderful 294: coincidence that the offset 295: for car is the same as for 296: discipline so we get bcd macros 297: for free here ! */ 298: if(dopopframe) errp = Popframe(); 299: Restorestack(); 300: return(vtemp); 301: } 302: popnames(oldbnp); 303: a = (lispval) errorh1(Verundef,"eval: Undefined function ",nil,TRUE,0,actarg->d.car); 304: } 305: 306: } 307: if(dopopframe) errp = Popframe(); 308: Restorestack(); 309: return(a); /* other data types are considered constants */ 310: } 311: 312: /* 313: * popnames 314: * removes from the name stack all entries above the first argument. 315: * routine should usually be used to clean up the name stack as it 316: * knows about the special cases. bnp is returned pointing to the 317: * same place as the argument passed. 318: */ 319: lispval 320: popnames(llimit) 321: register struct nament *llimit; 322: { 323: register struct nament *rnp; 324: 325: for(rnp = bnp; --rnp >= llimit;) 326: rnp->atm->a.clb = rnp->val; 327: bnp = llimit; 328: } 329: 330: 331: /* dumpnamestack 332: * utility routine to dump out the namestack. 333: * from bottom to 5 above np 334: * should be put elsewhere 335: */ 336: dumpnamestack() 337: { 338: struct argent *newnp; 339: 340: printf("namestack dump:\n"); 341: for(newnp = orgnp ; (newnp < np + 6) && (newnp < nplim) ; newnp++) 342: { 343: if(newnp == np) printf("**np:**\n"); 344: printf("[%d]: ",newnp-orgnp); 345: printr(newnp->val,stdout); 346: printf("\n"); 347: } 348: printf("end namestack dump\n"); 349: } 350: 351: 352: 353: lispval 354: Lapply() 355: { 356: register lispval a; 357: register lispval handy; 358: lispval vtemp, Ifclosure(); 359: struct nament *oldbnp = bnp; 360: struct argent *oldlbot = lbot; /* Bottom of my frame! */ 361: struct argent *oldnp = np; /* First free on stack */ 362: int extrapush; /* if must save function value */ 363: 364: a = lbot->val; 365: argptr = lbot[1].val; 366: if(np-lbot!=2) 367: errorh2(Vermisc,"Apply: Wrong number of args.",nil,FALSE, 368: 999,a,argptr); 369: if(TYPE(argptr)!=DTPR && argptr!=nil) 370: argptr = errorh1(Vermisc,"Apply: non-list of args",nil,TRUE, 371: 998,argptr); 372: (np++)->val = a; /* push form on namestack */ 373: TNP; 374: lbot = np; /* bottom of current frame */ 375: for(EVER) 376: { 377: extrapush = 0; 378: if (TYPE(a) == ATOM) { a = a->a.fnbnd; extrapush = 1; } 379: /* get function definition (unless 380: calling form is itself a lambda- 381: expression) */ 382: vtemp = CNIL; /* sentinel value for error test */ 383: switch (TYPE(a)) { 384: 385: case BCD: 386: /* push arguments - value of a */ 387: if(a->bcd.discipline==nlambda || a->bcd.discipline==macro) { 388: (np++)->val=argptr; 389: TNP; 390: } else for (; argptr!=nil; argptr = argptr->d.cdr) { 391: (np++)->val=argptr->d.car; 392: TNP; 393: } 394: 395: if(TYPE(a->bcd.discipline) == STRNG) 396: vtemp = Ifcall(a); /* foreign function */ 397: else 398: vtemp = (*(lispval (*)())(a->bcd.start))(); /* go for it */ 399: break; 400: 401: case ARRAY: 402: vtemp = Iarray(a,argptr,FALSE); 403: break; 404: 405: 406: case DTPR: 407: if (a->d.car==nlambda || a->d.car==macro) { 408: (np++)->val = argptr; 409: TNP; 410: } else if (a->d.car==lambda) 411: for (; argptr!=nil; argptr = argptr->d.cdr) { 412: (np++)->val = argptr->d.car; 413: TNP; 414: } 415: else if(a->d.car==lexpr) { 416: for (; argptr!=nil; argptr = argptr->d.cdr) { 417: 418: (np++)->val = argptr->d.car; 419: TNP; 420: } 421: handy = newdot(); 422: handy->d.car = (lispval)lbot; 423: handy->d.cdr = (lispval)np; 424: PUSHDOWN(lexpr_atom,handy); 425: lbot = np; 426: (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car); 427: 428: } else break; /* something is wrong - this isnt a proper function */ 429: rebind(a->d.cdr->d.car,lbot); 430: 431: if (extrapush == 1) { protect(a); extrapush = 2;} 432: for (handy = a->d.cdr->d.cdr; 433: handy != nil; 434: handy = handy->d.cdr) { 435: vtemp = eval(handy->d.car); /* go for it */ 436: } 437: break; 438: 439: case VECTOR: 440: /* certain vectors are valid (fclosures) */ 441: if(a->v.vector[VPropOff] == fclosure) 442: vtemp = (lispval) Ifclosure(a,FALSE); 443: break; 444: 445: }; 446: 447: /* pop off extra value if we pushed it before */ 448: if (extrapush == 2) 449: { 450: np--; 451: extrapush = 0; 452: }; 453: 454: if (vtemp != CNIL) 455: /* if we get here with a believable value, */ 456: /* we must have executed a function. */ 457: { 458: popnames(oldbnp); 459: 460: /* in case some clown trashed t */ 461: 462: tatom->a.clb = (lispval) tatom; 463: np = oldnp; lbot = oldlbot; 464: return(vtemp); 465: } 466: popnames(oldbnp); 467: a = (lispval) errorh1(Verundef,"apply: Undefined Function ", 468: nil,TRUE,0,oldlbot->val); 469: } 470: /*NOT REACHED*/ 471: } 472: 473: 474: /* 475: * Rebind -- rebind formal names 476: */ 477: rebind(argptr,workp) 478: register lispval argptr; /* argptr points to list of atoms */ 479: register struct argent * workp; /* workp points to position on stack 480: where evaluated args begin */ 481: { 482: register struct nament *namptr = bnp; 483: 484: for(;argptr != (lispval)nil; 485: workp++,argptr = argptr->d.cdr) /* rebind formal names (shallow) */ 486: { 487: if(argptr->d.car==nil) 488: continue; 489: namptr->atm = argptr->d.car; 490: if (workp < np) { 491: namptr->val = namptr->atm->a.clb; 492: namptr->atm->a.clb = workp->val; 493: } else 494: bnp = namptr, 495: error("Too few actual parameters",FALSE); 496: namptr++; 497: if(namptr > bnplim) 498: binderr(); 499: } 500: bnp = namptr; 501: if (workp < np) 502: error("Too many actual parameters",FALSE); 503: } 504: 505: /* the argument to Lfuncal is now mandatory since nargs 506: * wont work on RISC. If it is given then it is 507: * the name of the function to call and lbot points to the first arg. 508: * if it is not given, then lbot points to the function to call 509: */ 510: lispval 511: Ifuncal(fcn) 512: lispval fcn; 513: { 514: register lispval a; 515: register lispval handy; 516: struct nament *oldbnp = bnp; /* MUST be first local for evalframe */ 517: lispval fcncalled; 518: lispval Ifcall(),Llist(),Iarray(), Ifclosure(); 519: lispval vtemp; 520: int typ, dopopframe = FALSE, extrapush; 521: extern lispval end[]; 522: Savestack(3); 523: 524: /*if(nargs()==1) /* function I am evaling. */ 525: a = fcncalled = fcn; 526: /*else { a = fcncalled = lbot->val; lbot++; }*/ 527: 528: /*debugging 529: if (rsetsw && rsetatom->a.clb != nil) { 530: printf("funcall:"); 531: printr(a,stdout); 532: printf("\nrsetsw: %d evalhsw: %d\n", rsetsw, evalhsw); 533: printf("*rset: "); 534: printr(rsetatom->a.clb,stdout); 535: printf(" funhook: "); 536: printr(funhatom->a.clb,stdout); 537: printf(" funhook call flag^G: %d\n",funhcallsw); 538: fflush(stdout); 539: }; 540: */ 541: 542: /* check if exception pending */ 543: if(sigintcnt > 0 ) sigcall(SIGINT); 544: 545: if (rsetsw && rsetatom->a.clb != nil) /* if (*rset t) has been done */ 546: { 547: pbuf pb; 548: if (evalhsw != nil && funhatom->a.clb != nil) 549: { 550: /*if (sstatus evalhook t) 551: and evalhook non-nil */ 552: if (!funhcallsw) 553: /*if we got here after calling funcallhook, then 554: funhcallsw will be TRUE, so we want to skip calling 555: the hook function, permitting one form to be 556: evaluated before the hook fires. 557: */ 558: { 559: /* setup equivalent of (funcall funcallhook <args to eval>) */ 560: protect(a); 561: a = fcncalled = funhatom->a.clb; /* new function to funcall */ 562: PUSHDOWN(funhatom, nil); /* lambda-bind 563: * funcallhook to nil 564: */ 565: PUSHDOWN(evalhatom, nil); 566: /* printf(" now will funcall "); 567: printr(a,stdout); 568: putchar('\n'); 569: fflush(stdout); */ 570: }; 571: } 572: errp = Pushframe(F_FUNCALL,a,nil); 573: dopopframe = TRUE; /* remember to pop later */ 574: if(retval == C_FRETURN) 575: { 576: popnames(oldbnp); 577: errp = Popframe(); 578: Restorestack(); 579: return(lispretval); 580: } 581: }; 582: 583: funhcallsw = FALSE; /* so recursive calls to funcall will cause hook 584: to fire */ 585: for(EVER) 586: { 587: top: 588: extrapush = 0; 589: 590: typ = TYPE(a); 591: if (typ == ATOM) 592: { /* get function defn (unless calling form */ 593: /* is itself a lambda-expr) */ 594: a = a->a.fnbnd; 595: typ = TYPE(a); 596: extrapush = 1; /* must protect this later */ 597: } 598: vtemp = CNIL-1; /* sentinel value for error test */ 599: switch (typ) { 600: case ARRAY: 601: protect(a); /* stack array descriptor on top */ 602: a = a->ar.accfun; /* now funcall access function */ 603: goto top; 604: case BCD: 605: if(a->bcd.discipline==nlambda) 606: { if(np==lbot) protect(nil); /* default is nil */ 607: while(np-lbot!=1 || (lbot->val != nil && 608: TYPE(lbot->val)!=DTPR)) { 609: 610: lbot->val = errorh1(Vermisc,"Bad funcall arg(s) to fexpr.", 611: nil,TRUE,0,lbot->val); 612: 613: np = lbot+1; 614: } 615: } 616: /* go for it */ 617: 618: if(TYPE(a->bcd.discipline)==STRNG) 619: vtemp = Ifcall(a); 620: else 621: vtemp = (*(lispval (*)())(a->bcd.start))(); 622: if(a->bcd.discipline==macro) 623: vtemp = eval(vtemp); 624: break; 625: 626: 627: case DTPR: 628: if (a->d.car == lambda) { 629: ;/* VOID */ 630: } else if (a->d.car == nlambda || a->d.car==macro) { 631: if( np==lbot ) protect(nil); /* default */ 632: while(np-lbot!=1 || (lbot->val != nil && 633: TYPE(lbot->val)!=DTPR)) { 634: lbot->val = error("Bad funcall arg(s) to fexpr.",TRUE); 635: np = lbot+1; 636: } 637: } else if (a->d.car == lexpr) { 638: handy = newdot(); 639: handy->d.car = (lispval) lbot; 640: handy->d.cdr = (lispval) np; 641: PUSHDOWN(lexpr_atom,handy); 642: lbot = np; 643: (np++)->val = inewint(((lispval *)handy->d.cdr) - (lispval *)handy->d.car); 644: } else break; /* something is wrong - this isn't a proper function */ 645: rebind(a->d.cdr->d.car,lbot); 646: 647: /* since the actual arguments are bound to their formal params 648: * we can pop them off the stack. However if we are doing 649: * debugging (that is if we've pushed a frame on the stack) 650: * then we must not pop off the actual args since they must 651: * be visible for evalframe to work 652: */ 653: if(!dopopframe) np = lbot; 654: if (extrapush == 1) {protect(a); extrapush = 2;} 655: for (handy = a->d.cdr->d.cdr; 656: handy != nil; 657: handy = handy->d.cdr) { 658: vtemp = eval(handy->d.car); /* go for it */ 659: } 660: if(a->d.car==macro) 661: vtemp = eval(vtemp); 662: break; 663: 664: case VECTOR: 665: /* A fclosure represented as a vector with the property 'fclosure' */ 666: if(a->v.vector[VPropOff] == fclosure) 667: vtemp = (lispval) Ifclosure(a,TRUE); 668: break; 669: 670: } 671: 672: /* pop off extra value if we pushed it before */ 673: if(extrapush == 2) { np-- ; extrapush = 0; } 674: 675: if (vtemp != CNIL-1) 676: /* if we get here with a believable value, */ 677: /* we must have executed a function. */ 678: { 679: popnames(oldbnp); 680: 681: /* in case some clown trashed t */ 682: 683: tatom->a.clb = (lispval) tatom; 684: 685: if(dopopframe) errp = Popframe(); 686: Restorestack(); 687: return(vtemp); 688: } 689: popnames(oldbnp); 690: a = fcncalled = (lispval) errorh1(Verundef,"funcall: Bad function", 691: nil,TRUE,0,fcncalled); 692: } 693: /*NOT REACHED*/ 694: } 695: lispval /* this version called from lisp */ 696: Lfuncal() 697: { 698: lispval handy; 699: Savestack(0); 700: 701: switch(np-lbot) 702: { 703: case 0: argerr("funcall"); 704: break; 705: } 706: handy = lbot++->val; 707: handy = Ifuncal(handy); 708: Restorestack(); 709: return(handy); 710: } 711: 712: /* The following must be the next "function" after Lfuncal, for the 713: sake of Levalf. */ 714: fchack () {} 715: 716: 717: /* 718: * Llexfun :: lisp function lexpr-funcall 719: * lexpr-funcall is a cross between funcall and apply. 720: * the last argument is nil or a list of the rest of the arguments. 721: * we push those arguments on the stack and call funcall 722: * 723: */ 724: lispval 725: Llexfun() 726: { 727: register lispval handy; 728: 729: switch(np-lbot) 730: { 731: case 0: argerr("lexpr-funcall"); /* need at least one arg */ 732: break; 733: case 1: return(Lfuncal()); /* no args besides function */ 734: } 735: /* have at least one argument past the function to funcall */ 736: handy = np[-1].val; /* get last value */ 737: np--; /* pop it off stack */ 738: 739: while((handy != nil) && (TYPE(handy) != DTPR)) 740: handy = errorh1(Vermisc,"lexpr-funcall: last argument is not a list ", 741: nil,TRUE,0,handy); 742: 743: /* stack arguments */ 744: for( ; handy != nil ; handy = handy->d.cdr) protect(handy->d.car); 745: 746: return(Lfuncal()); 747: } 748: 749: 750: #undef protect 751: 752: /* protect 753: * pushes the first argument onto namestack, thereby protecting from gc 754: */ 755: lispval 756: protect(a) 757: lispval a; 758: { 759: (np++)->val = a; 760: if (np >= nplim) 761: namerr(); 762: } 763: 764: /* unprot 765: * returns the top thing on the name stack. Underflow had better not 766: * occur. 767: */ 768: lispval 769: unprot() 770: { 771: return((--np)->val); 772: } 773: 774: lispval 775: linterp() 776: { 777: error("BYTE INTERPRETER CALLED ERRONEOUSLY",FALSE); 778: } 779: 780: /* Undeff - called from qfuncl when it detects a call to a undefined 781: function from compiled code, we print out a message and 782: will continue only if returned a symbol (ATOM in C parlance). 783: */ 784: lispval 785: Undeff(atmn) 786: lispval atmn; 787: { 788: do {atmn =errorh1(Verundef,"Undefined function called from compiled code ", 789: nil,TRUE,0,atmn);} 790: while(TYPE(atmn) != ATOM); 791: return(atmn); 792: } 793: 794: /* VARARGS1 */ 795: bindfix(firstarg) 796: lispval firstarg; 797: { 798: register lispval *argp = &firstarg; 799: register struct nament *mybnp = bnp; 800: while(*argp != nil) { 801: mybnp->atm = *argp++; 802: mybnp->val = mybnp->atm->a.clb; 803: mybnp->atm->a.clb = *argp++; 804: bnp = mybnp++; 805: } 806: }