|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: fex1.c,v 1.3 83/09/07 17:55:28 sklower Exp $"; ! 4: #endif ! 5: ! 6: /* -[Sat Mar 5 19:50:28 1983 by layer]- ! 7: * fex1.c $Locker: $ ! 8: * nlambda functions ! 9: * ! 10: * (c) copyright 1982, Regents of the University of California ! 11: */ ! 12: ! 13: ! 14: #include "global.h" ! 15: #include "frame.h" ! 16: ! 17: /* Nprog ****************************************************************/ ! 18: /* This first sets the local variables to nil while saving their old */ ! 19: /* values on the name stack. Then, pointers to various things are */ ! 20: /* saved as this function may be returned to by an "Ngo" or by a */ ! 21: /* "Lreturn". At the end is the loop that cycles through the contents */ ! 22: /* of the prog. */ ! 23: ! 24: lispval ! 25: Nprog() { ! 26: register lispval where, temp; ! 27: struct nament *savedbnp = bnp; ! 28: extern struct frame *errp; ! 29: pbuf pb; ! 30: extern int retval; ! 31: extern lispval lispretval; ! 32: ! 33: if((np-lbot) < 1) chkarg(1,"prog"); ! 34: ! 35: /* shallow bind the local variables to nil */ ! 36: if(lbot->val->d.car != nil) ! 37: { ! 38: for( where = lbot->val->d.car ; where != nil; where = where->d.cdr ) ! 39: { ! 40: if(TYPE(where) != DTPR || TYPE(temp=where->d.car) != ATOM) ! 41: errorh1(Vermisc, ! 42: "Illegal local variable list in prog ",nil,FALSE, ! 43: 1,where); ! 44: PUSHDOWN(temp,nil); ! 45: } ! 46: } ! 47: ! 48: /* put a frame on the stack which can be 'return'ed to or 'go'ed to */ ! 49: errp = Pushframe(F_PROG,nil,nil); ! 50: ! 51: where = lbot->val->d.cdr; /* first thing in the prog body */ ! 52: ! 53: switch (retval) { ! 54: case C_RET: /* ! 55: * returning from this prog, value to return ! 56: * is in lispretval ! 57: */ ! 58: errp = Popframe(); ! 59: popnames(savedbnp); ! 60: return(lispretval); ! 61: ! 62: case C_GO: /* ! 63: * going to a certain label, label to go to in ! 64: * in lispretval ! 65: */ ! 66: where = (lbot->val)->d.cdr; ! 67: while ((TYPE(where) == DTPR) ! 68: && (where->d.car != lispretval)) ! 69: where = where->d.cdr; ! 70: if (where->d.car == lispretval) { ! 71: popnames(errp->svbnp); ! 72: break; ! 73: } ! 74: /* label not found in this prog, must ! 75: * go up to higher prog ! 76: */ ! 77: errp = Popframe(); /* go to next frame */ ! 78: Inonlocalgo(C_GO,lispretval,nil); ! 79: ! 80: /* NOT REACHED */ ! 81: ! 82: case C_INITIAL: break; ! 83: ! 84: } ! 85: ! 86: while (TYPE(where) == DTPR) ! 87: { ! 88: temp = where->d.car; ! 89: if((TYPE(temp))!=ATOM) eval(temp); ! 90: where = where->d.cdr; ! 91: } ! 92: if((where != nil) && (TYPE(where) != DTPR)) ! 93: errorh1(Vermisc,"Illegal form in prog body ", nil,FALSE,0,where); ! 94: errp = Popframe(); ! 95: popnames(savedbnp); /* pop off locals */ ! 96: return(nil); ! 97: } ! 98: ! 99: lispval globtag; ! 100: /* ! 101: Ncatch is now linked to the lisp symbol *catch , which has the form ! 102: (*catch tag form) ! 103: tag is evaluated and then the catch entry is set up. ! 104: then form is evaluated ! 105: finally the catch entry is removed. ! 106: ! 107: *catch is still an nlambda since its arguments should not be evaluated ! 108: before this routine is called. ! 109: ! 110: (catch form [tag]) is translated to (*catch 'tag form) by a macro. ! 111: */ ! 112: lispval ! 113: Ncatch() ! 114: { ! 115: register lispval tag; ! 116: pbuf pb; ! 117: Savestack(3); /* save stack pointers */ ! 118: ! 119: if((TYPE(lbot->val))!=DTPR) return(nil); ! 120: protect(tag = eval(lbot->val->d.car)); /* protect tag from gc */ ! 121: ! 122: errp = Pushframe(F_CATCH,tag,nil); ! 123: ! 124: switch(retval) { ! 125: ! 126: case C_THROW: /* ! 127: * value thrown is in lispretval ! 128: */ ! 129: break; ! 130: ! 131: case C_INITIAL: /* ! 132: * calculate value of expression ! 133: */ ! 134: lispretval = eval(lbot->val->d.cdr->d.car); ! 135: } ! 136: ! 137: ! 138: errp = Popframe(); ! 139: Restorestack(); ! 140: return(lispretval); ! 141: } ! 142: /* (errset form [flag]) ! 143: if present, flag determines if the error message will be printed ! 144: if an error reaches the errset. ! 145: if no error occurs, errset returns a list of one element, the ! 146: value returned from form. ! 147: if an error occurs, nil is usually returned although it could ! 148: be non nil if err threw a non nil value ! 149: */ ! 150: ! 151: lispval Nerrset() ! 152: { ! 153: lispval temp,flag; ! 154: pbuf pb; ! 155: Savestack(0); ! 156: ! 157: if(TYPE(lbot->val) != DTPR) return(nil); /* no form */ ! 158: ! 159: /* evaluate and save flag first */ ! 160: flag = lbot->val->d.cdr; ! 161: if(TYPE(flag) == DTPR) flag = eval(flag->d.car); ! 162: else flag = tatom; /* if not present , assume t */ ! 163: protect(flag); ! 164: ! 165: errp = Pushframe(F_CATCH,Verall,flag); ! 166: ! 167: switch(retval) { ! 168: ! 169: case C_THROW: /* ! 170: * error thrown to this routine, value thrown is ! 171: * in lispretval ! 172: */ ! 173: break; ! 174: ! 175: case C_INITIAL: /* ! 176: * normally just evaluate expression and listify it. ! 177: */ ! 178: temp = eval(lbot->val->d.car); ! 179: protect(temp); ! 180: (lispretval = newdot())->d.car = temp; ! 181: break; ! 182: } ! 183: ! 184: errp = Popframe(); ! 185: Restorestack(); ! 186: return(lispretval); ! 187: } ! 188: ! 189: /* this was changed from throw to *throw 21nov79 ! 190: it is now a lambda and really should be called Lthrow ! 191: */ ! 192: lispval ! 193: Nthrow() ! 194: { ! 195: switch(np-lbot) { ! 196: case 0: ! 197: protect(nil); ! 198: case 1: ! 199: protect(nil); ! 200: case 2: break; ! 201: default: ! 202: argerr("throw"); ! 203: } ! 204: Inonlocalgo(C_THROW,lbot->val,(lbot+1)->val); ! 205: /* NOT REACHED */ ! 206: } ! 207: ! 208: ! 209: ! 210: /* Ngo ******************************************************************/ ! 211: /* First argument only is checked - and must be an atom or evaluate */ ! 212: /* to one. */ ! 213: lispval ! 214: Ngo() ! 215: { ! 216: register lispval temp; ! 217: chkarg(1,"go"); ! 218: ! 219: temp = (lbot->val)->d.car; ! 220: if (TYPE(temp) != ATOM) ! 221: { ! 222: temp = eval(temp); ! 223: while(TYPE(temp) != ATOM) ! 224: temp = errorh1(Vermisc,"Illegal tag to go to",nil,TRUE, 0,lbot->val); ! 225: } ! 226: Inonlocalgo(C_GO,temp,nil); ! 227: /* NOT REACHED */ ! 228: } ! 229: ! 230: ! 231: /* Nreset ***************************************************************/ ! 232: /* All arguments are ignored. This just returns-from-break to depth 0. */ ! 233: lispval ! 234: Nreset() ! 235: { ! 236: Inonlocalgo(C_RESET,inewint(0),nil); ! 237: } ! 238: ! 239: /* Nresetio *************************************************************/ ! 240: ! 241: lispval ! 242: Nresetio() { ! 243: register FILE *p; ! 244: ! 245: for(p = &_iob[3]; p < _iob + _NFILE; p++) { ! 246: if(p->_flag & (_IOWRT | _IOREAD)) fclose(p); ! 247: } ! 248: return(nil); ! 249: ! 250: } ! 251: ! 252: ! 253: /* Nbreak ***************************************************************/ ! 254: /* If first argument is not nil, this is evaluated and printed. Then */ ! 255: /* error is called with the "breaking" message. */ ! 256: ! 257: lispval ! 258: Nbreak() ! 259: { ! 260: register lispval hold; register FILE *port; ! 261: port = okport(Vpoport->a.clb,stdout); ! 262: fprintf(port,"Breaking:"); ! 263: ! 264: if ((hold = lbot->val) != nil && ((hold = hold->d.car) != nil)) ! 265: { ! 266: printr(hold,port); ! 267: } ! 268: putc('\n',port); ! 269: dmpport(port); ! 270: return(errorh(Verbrk,"",nil,TRUE,0)); ! 271: } ! 272: ! 273: ! 274: /* Nexit ****************************************************************/ ! 275: /* Just calls lispend with no message. */ ! 276: Nexit() ! 277: { ! 278: lispend(""); ! 279: } ! 280: ! 281: ! 282: /* Nsys *****************************************************************/ ! 283: /* Just calls lispend with no message. */ ! 284: ! 285: lispval ! 286: Nsys() ! 287: { ! 288: lispend(""); ! 289: } ! 290: ! 291: ! 292: ! 293: ! 294: lispval ! 295: Ndef() { ! 296: register lispval arglist, body, name, form; ! 297: ! 298: form = lbot->val; ! 299: name = form->d.car; ! 300: body = form->d.cdr->d.car; ! 301: arglist = body->d.cdr->d.car; ! 302: if((TYPE(arglist))!=DTPR && arglist != nil) ! 303: error("Warning: defining function with nonlist of args", ! 304: TRUE); ! 305: name->a.fnbnd = body; ! 306: return(name); ! 307: } ! 308: ! 309: ! 310: lispval ! 311: Nquote() ! 312: { ! 313: return((lbot->val)->d.car); ! 314: } ! 315: ! 316: ! 317: lispval ! 318: Nsetq() ! 319: { register lispval handy, where, value; ! 320: register int lefttype; ! 321: ! 322: value = nil; ! 323: ! 324: for(where = lbot->val; where != nil; where = handy->d.cdr) { ! 325: handy = where->d.cdr; ! 326: if((TYPE(handy))!=DTPR) ! 327: error("odd number of args to setq",FALSE); ! 328: if((lefttype=TYPE(where->d.car))==ATOM) { ! 329: if(where->d.car==nil) ! 330: error("Attempt to set nil",FALSE); ! 331: where->d.car->a.clb = value = eval(handy->d.car); ! 332: }else if(lefttype==VALUE) ! 333: where->d.car->l = value = eval(handy->d.car); ! 334: else errorh1(Vermisc, ! 335: "Can only setq atoms or values",nil,FALSE,0, ! 336: where->d.car); ! 337: } ! 338: return(value); ! 339: } ! 340: ! 341: ! 342: lispval ! 343: Ncond() ! 344: { ! 345: register lispval where, last; ! 346: ! 347: where = lbot->val; ! 348: last = nil; ! 349: for(;;) { ! 350: if ((TYPE(where))!=DTPR) ! 351: break; ! 352: if ((TYPE(where->d.car))!=DTPR) ! 353: break; ! 354: if ((last=eval((where->d.car)->d.car)) != nil) ! 355: break; ! 356: where = where->d.cdr; ! 357: } ! 358: ! 359: if ((TYPE(where)) != DTPR) ! 360: return(nil); ! 361: where = (where->d.car)->d.cdr; ! 362: while ((TYPE(where))==DTPR) { ! 363: last = eval(where->d.car); ! 364: where = where->d.cdr; ! 365: } ! 366: return(last); ! 367: } ! 368: ! 369: lispval ! 370: Nand() ! 371: { ! 372: register lispval current, temp; ! 373: ! 374: current = lbot->val; ! 375: temp = tatom; ! 376: while (current != nil) ! 377: if ( (temp = current->d.car)!=nil && (temp = eval(temp))!=nil) ! 378: current = current->d.cdr; ! 379: else { ! 380: current = nil; ! 381: temp = nil; ! 382: } ! 383: return(temp); ! 384: } ! 385: ! 386: ! 387: lispval ! 388: Nor() ! 389: { ! 390: register lispval current, temp; ! 391: ! 392: current = lbot->val; ! 393: temp = nil; ! 394: while (current != nil) ! 395: if ( (temp = eval(current->d.car)) == nil) ! 396: current = current->d.cdr; ! 397: else ! 398: break; ! 399: return(temp); ! 400: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.