|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: lam8.c,v 1.9 83/09/12 14:16:52 sklower Exp $"; ! 4: #endif ! 5: ! 6: /* -[Fri Aug 12 07:54:00 1983 by jkf]- ! 7: * lam8.c $Locker: $ ! 8: * lambda functions ! 9: * ! 10: * (c) copyright 1982, Regents of the University of California ! 11: */ ! 12: ! 13: #include "global.h" ! 14: #include <sys/types.h> ! 15: #include <sys/stat.h> ! 16: #include "frame.h" ! 17: ! 18: /* various functions from the c math library */ ! 19: double sin(),cos(),asin(),acos(),atan2(),sqrt(), log(), exp(); ! 20: extern int current; ! 21: ! 22: lispval Imath(func) ! 23: double (*func)(); ! 24: { ! 25: register lispval handy; ! 26: register double res; ! 27: chkarg(1,"Math functions"); ! 28: ! 29: switch(TYPE(handy=lbot->val)) { ! 30: case INT: res = func((double)handy->i); ! 31: break; ! 32: ! 33: case DOUB: res = func(handy->r); ! 34: break; ! 35: ! 36: default: error("Non fixnum or flonum to math function",FALSE); ! 37: } ! 38: handy = newdoub(); ! 39: handy->r = res; ! 40: return(handy); ! 41: } ! 42: lispval Lsin() ! 43: { ! 44: return(Imath(sin)); ! 45: } ! 46: ! 47: lispval Lcos() ! 48: { ! 49: return(Imath(cos)); ! 50: } ! 51: ! 52: lispval Lasin() ! 53: { ! 54: return(Imath(asin)); ! 55: } ! 56: ! 57: lispval Lacos() ! 58: { ! 59: return(Imath(acos)); ! 60: } ! 61: ! 62: lispval Lsqrt() ! 63: { ! 64: return(Imath(sqrt)); ! 65: } ! 66: lispval Lexp() ! 67: { ! 68: return(Imath(exp)); ! 69: } ! 70: ! 71: lispval Llog() ! 72: { ! 73: return(Imath(log)); ! 74: } ! 75: ! 76: /* although we call this atan, it is really atan2 to the c-world, ! 77: that is, it takes two args ! 78: */ ! 79: lispval Latan() ! 80: { ! 81: register lispval arg; ! 82: register double arg1v; ! 83: register double res; ! 84: chkarg(2,"arctan"); ! 85: ! 86: switch(TYPE(arg=lbot->val)) { ! 87: ! 88: case INT: arg1v = (double) arg->i; ! 89: break; ! 90: ! 91: case DOUB: arg1v = arg->r; ! 92: break; ! 93: ! 94: default: error("Non fixnum or flonum arg to atan2",FALSE); ! 95: } ! 96: ! 97: switch(TYPE(arg = (lbot+1)->val)) { ! 98: ! 99: case INT: res = atan2(arg1v,(double) arg->i); ! 100: break; ! 101: ! 102: case DOUB: res = atan2(arg1v, arg->r); ! 103: break; ! 104: ! 105: default: error("Non fixnum or flonum to atan2",FALSE); ! 106: } ! 107: arg = newdoub(); ! 108: arg->r = res; ! 109: return(arg); ! 110: } ! 111: ! 112: /* (random) returns a fixnum in the range -2**30 to 2**30 -1 ! 113: (random fixnum) returns a fixnum in the range 0 to fixnum-1 ! 114: */ ! 115: lispval ! 116: Lrandom() ! 117: { ! 118: register int curval; ! 119: float pow(); ! 120: ! 121: curval = rand(); /* get numb from 0 to 2**31-1 */ ! 122: ! 123: if(np==lbot) return(inewint(curval-(int)pow((double)2,(double)30))); ! 124: ! 125: if((TYPE(lbot->val) != INT) ! 126: || (lbot->val->i <= 0)) errorh1(Vermisc,"random: non fixnum arg:", ! 127: nil, FALSE, 0, lbot->val); ! 128: ! 129: return(inewint(curval % lbot->val->i )); ! 130: ! 131: } ! 132: lispval ! 133: Lmakunb() ! 134: { ! 135: register lispval work; ! 136: ! 137: chkarg(1,"makunbound"); ! 138: work = lbot->val; ! 139: if(work==nil || (TYPE(work)!=ATOM)) ! 140: return(work); ! 141: work->a.clb = CNIL; ! 142: return(work); ! 143: } ! 144: ! 145: lispval ! 146: Lfseek() ! 147: { ! 148: ! 149: FILE *f; ! 150: long offset, whence; ! 151: lispval retp; ! 152: ! 153: chkarg(3,"fseek"); /* Make sure there are three arguments*/ ! 154: ! 155: f = lbot->val->p; /* Get first argument into f */ ! 156: if (TYPE(lbot->val)!=PORT) /* Check type of first */ ! 157: error("fseek: First argument must be a port.",FALSE); ! 158: ! 159: offset = lbot[1].val->i; /* Get second argument */ ! 160: if (TYPE(lbot[1].val)!=INT) ! 161: error("fseek: Second argument must be an integer.",FALSE); ! 162: ! 163: whence = lbot[2].val->i; /* Get last arg */ ! 164: if (TYPE(lbot[2].val)!=INT) ! 165: error("fseek: Third argument must be an integer.",FALSE); ! 166: ! 167: if (fseek(f, offset, (int)whence) == -1) ! 168: error("fseek: Illegal parameters.",FALSE); ! 169: ! 170: retp = inewint(ftell(f)); ! 171: ! 172: return((lispval) retp); ! 173: } ! 174: ! 175: /* function hashtabstat : return list of number of members in each bucket */ ! 176: lispval Lhashst() ! 177: { ! 178: register lispval handy,cur; ! 179: register struct atom *pnt; ! 180: int i,cnt; ! 181: extern int hashtop; ! 182: Savestack(3); ! 183: ! 184: handy = newdot(); ! 185: protect(handy); ! 186: cur = handy; ! 187: for(i = 0; i < hashtop; i++) ! 188: { ! 189: pnt = hasht[i]; ! 190: for(cnt = 0; pnt != (struct atom *) CNIL ; pnt=pnt->hshlnk , cnt++); ! 191: cur->d.cdr = newdot(); ! 192: cur = cur->d.cdr; ! 193: cur->d.car = inewint(cnt); ! 194: } ! 195: cur->d.cdr = nil; ! 196: Restorestack(); ! 197: return(handy->d.cdr); ! 198: } ! 199: ! 200: ! 201: /* Lctcherr ! 202: this routine should only be called by the unwind protect simulation ! 203: lisp code ! 204: It is called after an unwind-protect frame has been entered and ! 205: evalated and we want to get on with the error or throw ! 206: We only handle the case where there are 0 to 2 extra arguments to the ! 207: error call. ! 208: */ ! 209: lispval ! 210: Lctcherr() ! 211: { ! 212: register lispval handy; ! 213: lispval type,messg,valret,contuab,uniqid,datum1,datum2; ! 214: ! 215: chkarg(1,"I-throw-err"); ! 216: ! 217: handy = lbot->val; ! 218: ! 219: if(TYPE(handy->d.car) == INT) ! 220: { /* continuing a non error (throw,reset, etc) */ ! 221: Inonlocalgo((int)handy->d.car->i, ! 222: handy->d.cdr->d.car, ! 223: handy->d.cdr->d.cdr->d.car); ! 224: /* NOT REACHED */ ! 225: } ! 226: ! 227: if(handy->d.car != nil) ! 228: { ! 229: errorh1(Vermisc,"I-do-throw: first element not fixnum or nil", ! 230: nil,FALSE,0,handy); ! 231: } ! 232: ! 233: /* decode the arg list */ ! 234: handy = handy->d.cdr; ! 235: type = handy->d.car; ! 236: handy = handy->d.cdr; ! 237: messg = handy->d.car; ! 238: handy = handy->d.cdr; ! 239: valret = handy->d.car; ! 240: handy = handy->d.cdr; ! 241: contuab = handy->d.car; ! 242: handy = handy->d.cdr; ! 243: uniqid = handy->d.car; ! 244: handy = handy->d.cdr; ! 245: ! 246: /* if not extra args */ ! 247: if(handy == nil) ! 248: { ! 249: errorh(type,messg->a.pname,valret,(int)contuab->i,(int)uniqid->i); ! 250: } ! 251: datum1 = handy->d.car; ! 252: handy = handy->d.cdr; ! 253: ! 254: /* if one extra arg */ ! 255: if(handy == nil) ! 256: { ! 257: errorh1(type,messg->a.pname,valret,(int)contuab->i,(int)uniqid->i,datum1); ! 258: } ! 259: ! 260: /* if two or more extra args, just use first 2 */ ! 261: datum2 = handy->d.car; ! 262: errorh2(type,messg->a.pname,valret,(int)contuab->i,(int)uniqid->i,datum1,datum2); ! 263: } ! 264: ! 265: /* ! 266: * (*makhunk '<fixnum>) ! 267: * <fixnum> ! 268: * Create a hunk of size 2 . <fixnum> must be between 0 and 6. ! 269: * ! 270: */ ! 271: ! 272: lispval ! 273: LMakhunk() ! 274: { ! 275: register int hsize, hcntr; ! 276: register lispval result; ! 277: ! 278: chkarg(1,"Makehunk"); ! 279: if (TYPE(lbot->val)==INT) ! 280: { ! 281: hsize = lbot->val->i; /* size of hunk (0-6) */ ! 282: if ((hsize >= 0) && (hsize <= 6)) ! 283: { ! 284: result = newhunk(hsize); ! 285: hsize = 2 << hsize; /* size of hunk (2-128) */ ! 286: for (hcntr = 0; hcntr < hsize; hcntr++) ! 287: result->h.hunk[hcntr] = hunkfree; ! 288: } ! 289: else ! 290: error("*makhunk: Illegal hunk size", FALSE); ! 291: return(result); ! 292: } ! 293: else ! 294: error("*makhunk: First arg must be an fixnum",FALSE); ! 295: /* NOTREACHED */ ! 296: } ! 297: ! 298: /* ! 299: * (cxr '<fixnum> '<hunk>) ! 300: * Returns the <fixnum>'th element of <hunk> ! 301: * ! 302: */ ! 303: lispval ! 304: Lcxr() ! 305: { ! 306: register lispval temp; ! 307: ! 308: chkarg(2,"cxr"); ! 309: if (TYPE(lbot->val)!=INT) ! 310: error("cxr: First arg must be a fixnum", FALSE); ! 311: else ! 312: { ! 313: if (! HUNKP(lbot[1].val)) ! 314: error("cxr: Second arg must be a hunk", FALSE); ! 315: else ! 316: if ( (lbot->val->i >= 0) && ! 317: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) ) ! 318: { ! 319: temp = lbot[1].val->h.hunk[lbot->val->i]; ! 320: if (temp != hunkfree) ! 321: return(temp); ! 322: else ! 323: error("cxr: Arg outside of hunk range", ! 324: FALSE); ! 325: } ! 326: else ! 327: error("cxr: Arg outside of hunk range", FALSE); ! 328: } ! 329: /* NOTREACHED */ ! 330: } ! 331: ! 332: /* ! 333: * (rplacx '<fixnum> '<hunk> '<expr>) ! 334: * Replaces the <fixnum>'th element of <hunk> with <expr>. ! 335: * ! 336: */ ! 337: lispval ! 338: Lrplacx() ! 339: { ! 340: lispval *handy; ! 341: chkarg(3,"rplacx"); ! 342: if (TYPE(lbot->val)!=INT) ! 343: error("rplacx: First arg must be a fixnum", FALSE); ! 344: else ! 345: { ! 346: if (! HUNKP(lbot[1].val)) ! 347: error("rplacx: Second arg must be a hunk", FALSE); ! 348: else ! 349: { ! 350: if ( (lbot->val->i >= 0) && ! 351: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) ) ! 352: { ! 353: if (*(handy = &(lbot[1].val->h.hunk[lbot->val->i])) ! 354: != hunkfree) ! 355: *handy = lbot[2].val; ! 356: else ! 357: error("rplacx: Arg outside hunk range", FALSE); ! 358: } ! 359: else ! 360: error("rplacx: Arg outside hunk range", FALSE); ! 361: } ! 362: } ! 363: return(lbot[1].val); ! 364: } ! 365: ! 366: /* ! 367: * (*rplacx '<fixnum> '<hunk> '<expr>) ! 368: * Replaces the <fixnum>'th element of <hunk> with <expr>. This is the ! 369: * same as (rplacx ...) except with this function you can replace EMPTY's. ! 370: * ! 371: */ ! 372: lispval ! 373: Lstarrpx() ! 374: { ! 375: chkarg(3,"*rplacx"); ! 376: if (TYPE(lbot->val)!=INT) ! 377: error("*rplacx: First arg must be a fixnum", FALSE); ! 378: else ! 379: { ! 380: if (! HUNKP(lbot[1].val)) ! 381: error("*rplacx: Second arg must be a hunk", FALSE); ! 382: else ! 383: { ! 384: if ( (lbot->val->i >= 0) && ! 385: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) ) ! 386: lbot[1].val->h.hunk[lbot->val->i] = lbot[2].val; ! 387: else ! 388: error("*rplacx: Arg outside hunk range", FALSE); ! 389: } ! 390: } ! 391: return(lbot[1].val); ! 392: } ! 393: ! 394: /* ! 395: * (hunksize '<hunk>) ! 396: * Returns the size of <hunk> ! 397: * ! 398: */ ! 399: lispval ! 400: Lhunksize() ! 401: { ! 402: register int size,i; ! 403: ! 404: chkarg(1,"hunksize"); ! 405: if (HUNKP(lbot->val)) ! 406: { ! 407: size = 2 << HUNKSIZE(lbot->val); ! 408: for (i = size-1; i >= 0; i--) ! 409: { ! 410: if (lbot->val->h.hunk[i] != hunkfree) ! 411: { ! 412: size = i + 1; ! 413: break; ! 414: } ! 415: } ! 416: return( inewint(size) ); ! 417: } ! 418: else ! 419: error("hunksize: First argument must me a hunk", FALSE); ! 420: /* NOTREACHED */ ! 421: } ! 422: ! 423: /* ! 424: * (hunk-to-list 'hunk) returns a list of the hunk elements ! 425: */ ! 426: lispval ! 427: Lhtol() ! 428: { ! 429: register lispval handy,retval,last; ! 430: register int i; ! 431: int size; ! 432: Savestack(4); ! 433: ! 434: chkarg(1,"hunk-to-list"); ! 435: handy = lbot->val; ! 436: if(!(HUNKP(handy))) ! 437: errorh1(Vermisc,"hunk-to-list: non hunk argument: ", nil,0,FALSE, ! 438: handy); ! 439: size = 2 << HUNKSIZE(handy); ! 440: retval = nil; ! 441: for(i=0 ; i < size ; i++) ! 442: { ! 443: if(handy->h.hunk[i] != hunkfree) ! 444: { ! 445: if(retval==nil) ! 446: { ! 447: protect(retval=newdot()); ! 448: last = retval; ! 449: } ! 450: else { ! 451: last = (last->d.cdr = newdot()); ! 452: } ! 453: last->d.car = handy->h.hunk[i]; ! 454: } ! 455: else break; ! 456: } ! 457: Restorestack(); ! 458: return(retval); ! 459: } ! 460: ! 461: /* ! 462: * (fileopen filename mode) ! 463: * open a file for read, write, or append the arguments can be either ! 464: * strings or atoms. ! 465: */ ! 466: lispval ! 467: Lfileopen() ! 468: { ! 469: FILE *port; ! 470: register lispval name; ! 471: register lispval mode; ! 472: register char *namech; ! 473: register char *modech; ! 474: ! 475: chkarg(2,"fileopen"); ! 476: name = lbot->val; ! 477: mode = lbot[1].val; ! 478: ! 479: namech = (char *) verify(name,"fileopen:args must be atoms or strings"); ! 480: modech = (char *) verify(mode,"fileopen:args must be atoms or strings"); ! 481: ! 482: while (modech[0] != 'r' && modech[0] != 'w' && modech[0] != 'a') ! 483: { ! 484: mode = errorh(Vermisc,"Modes are only r, w, a.",nil,TRUE,31); ! 485: modech = (char *) verify(mode,"fileopen:args must be atoms or strings"); ! 486: } ! 487: ! 488: while ((port = fopen(namech, modech)) == NULL) ! 489: { ! 490: name = errorh1(Vermisc,"Unable to open file.",nil,TRUE,31,name); ! 491: namech = (char *) verify(name,"fileopen:args must be atoms or strings"); ! 492: } ! 493: /* xports is a FILE *, cc complains about adding pointers */ ! 494: ! 495: ioname[PN(port)] = (lispval) inewstr(namech); /* remember name */ ! 496: return( (lispval) (xports + (port - _iob))); ! 497: } ! 498: ! 499: /* ! 500: * (*invmod '<number> '<modulus>) ! 501: * This function returns the inverse of <number> ! 502: * mod <modulus> in balanced representation ! 503: * It is used in vaxima as a speed enhancement. ! 504: */ ! 505: ! 506: static lispval ! 507: Ibalmod(invmodp) ! 508: { ! 509: register long mod_div_2, number, modulus; ! 510: ! 511: chkarg(2,"*mod"); ! 512: if ((TYPE(lbot->val) == INT) && (TYPE(lbot[1].val) == INT)) ! 513: { ! 514: modulus = lbot[1].val->i; ! 515: if(invmodp) number = invmod(lbot->val->i , modulus); ! 516: else number = lbot->val->i % modulus; ! 517: mod_div_2 = modulus / 2; ! 518: if (number < 0) ! 519: { ! 520: if (number < (-mod_div_2)) ! 521: number += modulus; ! 522: } ! 523: else ! 524: { ! 525: if (number > mod_div_2) ! 526: number -= modulus; ! 527: } ! 528: return( inewint(number) ); ! 529: } ! 530: else ! 531: error("*mod: Arguments must be fixnums", FALSE); ! 532: /* NOTREACHED */ ! 533: } ! 534: ! 535: invmod (n,modulus) ! 536: long n , modulus; ! 537: ! 538: { ! 539: long a1,a2,a3,y1,y2,y3,q; ! 540: ! 541: a1 = modulus; ! 542: a2 = n; ! 543: y1 = 0; ! 544: y2= 1; ! 545: goto step3; ! 546: step2: ! 547: q = a1 /a2; /*truncated quotient */ ! 548: a3= mmuladd(modulus-a2,q,a1,modulus); ! 549: y3= mmuladd(modulus-y2,q,y1,modulus); ! 550: a1 = a2; ! 551: a2= a3; ! 552: y1=y2; ! 553: y2=y3; ! 554: step3: ! 555: if (a2==0) error("invmod: inverse of zero divisor",TRUE); ! 556: else if (a2 != 1) goto step2; ! 557: else return (y2); ! 558: /* NOTREACHED */ ! 559: } ! 560: ! 561: lispval ! 562: Lstarinvmod() ! 563: { ! 564: return(Ibalmod(TRUE)); ! 565: } ! 566: ! 567: /* ! 568: * (*mod '<number> '<modulus>) ! 569: * This function returns <number> mod <modulus> (for balanced modulus). ! 570: * It is used in vaxima as a speed enhancement. ! 571: */ ! 572: lispval ! 573: LstarMod() ! 574: { ! 575: return(Ibalmod(FALSE)); ! 576: } ! 577: ! 578: lispval ! 579: Llsh() ! 580: { ! 581: register struct argent *mylbot = lbot; ! 582: int val,shift; ! 583: ! 584: chkarg(2,"lsh"); ! 585: if((TYPE(mylbot->val) != INT) || (TYPE(mylbot[1].val) != INT)) ! 586: errorh2(Vermisc, ! 587: "Non ints to lsh", ! 588: nil,FALSE,0,mylbot->val,mylbot[1].val); ! 589: val = mylbot[0].val->i; ! 590: shift = mylbot[1].val->i; ! 591: if(shift < -32 || shift > 32) ! 592: return(inewint(0)); ! 593: if (shift < 0) ! 594: val = val >> -shift; ! 595: else ! 596: val = val << shift; ! 597: if((val < 0) && (shift < 0)) ! 598: { /* special case: the vax doesn't have a logical shift ! 599: instruction, so we must zero out the ones which ! 600: will propogate from the sign position ! 601: */ ! 602: return(inewint ( val & ~(0x80000000 << (shift+1)))); ! 603: } ! 604: else return( inewint(val)); ! 605: } ! 606: ! 607: /* very temporary function to test the validity of the bind stack */ ! 608: ! 609: bndchk() ! 610: { ! 611: register struct nament *npt; ! 612: register lispval in2; ! 613: ! 614: in2 = inewint(200); ! 615: for(npt=orgbnp; npt < bnp; npt++) ! 616: { if((int) npt->atm < (int) in2) abort(); ! 617: } ! 618: } ! 619: ! 620: /* ! 621: * formatted printer for lisp data ! 622: * use: (cprintf formatstring datum [port]) ! 623: */ ! 624: lispval ! 625: Lcprintf() ! 626: { ! 627: FILE *p; ! 628: char *fstrng; ! 629: lispval v; ! 630: if(np-lbot == 2) protect(nil); /* write to standard output port */ ! 631: chkarg(3,"cprintf"); ! 632: ! 633: fstrng = (char *)verify(lbot->val,"cprintf: first arg not string or symbol"); ! 634: ! 635: p = okport(lbot[2].val,okport(Vpoport->a.clb,poport)); ! 636: ! 637: switch(TYPE(v=lbot[1].val)) { ! 638: ! 639: case INT: fprintf(p,fstrng,v->i); ! 640: break; ! 641: ! 642: case DOUB: fprintf(p,fstrng,v->r); ! 643: break; ! 644: ! 645: case ATOM: fprintf(p,fstrng,v->a.pname); ! 646: break; ! 647: ! 648: case STRNG:fprintf(p,fstrng,v); ! 649: break; ! 650: ! 651: default: error("cprintf: Illegal second argument",FALSE); ! 652: }; ! 653: ! 654: return(lbot[1].val); ! 655: } ! 656: ! 657: ! 658: /* ! 659: * C style sprintf: (sprintf "format" {<arg-list>}) ! 660: * ! 661: * This function stacks the arguments onto the C stack in reverse ! 662: * order and then calls sprintf with one argument...This is what the ! 663: * C compiler does, so it works just fine. The return value is the ! 664: * string that is the result of the sprintf. ! 665: */ ! 666: lispval ! 667: Lsprintf() ! 668: { ! 669: register struct argent *argp; ! 670: register int j; ! 671: char sbuf[600], *sprintf(); /* better way? */ ! 672: Keepxs(); ! 673: ! 674: if (np-lbot == 0) { ! 675: argerr("sprintf"); ! 676: } ! 677: if (TYPE(lbot->val)==STRNG || TYPE(lbot->val)==INT) { ! 678: for (argp = np-1; argp >= lbot; argp--) { ! 679: switch(TYPE(argp->val)) { ! 680: case ATOM: ! 681: stack((long)argp->val->a.pname); ! 682: break; ! 683: ! 684: case DOUB: ! 685: #ifndef SPISFP ! 686: stack(argp->val->r); ! 687: #else ! 688: {double rr = argp->val->r; ! 689: stack(((long *)&rr)[1]); ! 690: stack(((long *)&rr)[0]);} ! 691: #endif ! 692: break; ! 693: ! 694: case INT: ! 695: stack(argp->val->i); ! 696: break; ! 697: ! 698: case STRNG: ! 699: stack((long)argp->val); ! 700: break; ! 701: ! 702: default: ! 703: error("sprintf: Bad data type to sprintf", ! 704: FALSE); ! 705: } ! 706: } ! 707: sprintf(sbuf); ! 708: for (j = 0; j < np-lbot; j++) ! 709: unstack(); ! 710: } else ! 711: error("sprintf: First arg must be an atom or string", FALSE); ! 712: Freexs(); ! 713: return ((lispval) inewstr(sbuf)); ! 714: } ! 715: ! 716: lispval ! 717: Lprobef() ! 718: { ! 719: char *name; ! 720: chkarg(1,"probef"); ! 721: ! 722: name = (char *)verify(lbot->val,"probef: not symbol or string arg "); ! 723: ! 724: if(access(name,0) == 0) return(tatom); ! 725: else return(nil); ! 726: } ! 727: ! 728: lispval ! 729: Lsubstring() ! 730: { register char *name; ! 731: register lispval index,length; ! 732: int restofstring = FALSE; ! 733: int len,ind,reallen; ! 734: ! 735: switch (np-lbot) ! 736: { ! 737: case 2: restofstring = TRUE; ! 738: break; ! 739: ! 740: case 3: break; ! 741: ! 742: default: chkarg(3,"substring"); ! 743: } ! 744: ! 745: name = (char *)verify(lbot[0].val,"substring: not symbol or string arg "); ! 746: ! 747: while (TYPE(index = lbot[1].val) != INT) ! 748: { lbot[1].val = errorh1(Vermisc,"substring: non integer index ",nil, ! 749: TRUE,0,index); ! 750: } ! 751: ! 752: len = strlen(name); ! 753: ind = index->i; ! 754: ! 755: if(ind < 0) ind = len+1 + ind; ! 756: ! 757: if(ind < 1 || ind > len) return(nil); /*index out of bounds*/ ! 758: if(restofstring) return((lispval)inewstr(name+ind-1)); ! 759: ! 760: while (TYPE(length = lbot[2].val) != INT) ! 761: { lbot[2].val = errorh1(Vermisc,"substring: not integer length ",nil, ! 762: TRUE,0,length); ! 763: } ! 764: ! 765: if((reallen = length->i ) < 0 || (reallen + ind) > len) ! 766: return((lispval)inewstr(name+ind-1)); ! 767: ! 768: strncpy(strbuf,name+ind-1,reallen); ! 769: strbuf[reallen] = '\0'; ! 770: return((lispval)newstr(0)); ! 771: } ! 772: ! 773: /* ! 774: * This is substringn ! 775: */ ! 776: lispval ! 777: Lsstrn() ! 778: { ! 779: register char *name; ! 780: register int len,ind,reallen; ! 781: lispval index,length; ! 782: int restofstring = FALSE; ! 783: Savestack(4); ! 784: ! 785: if((np-lbot) == 2) restofstring = TRUE; ! 786: else { chkarg(3,"substringn");} ! 787: ! 788: name = (char *) verify(lbot[0].val,"substringn: non symbol or string arg "); ! 789: ! 790: while (TYPE(index = lbot[1].val) != INT) ! 791: { lbot[1].val = errorh1(Vermisc,"substringn: non integer index ",nil, ! 792: TRUE,0,index); ! 793: } ! 794: ! 795: if(!restofstring) ! 796: { ! 797: while (TYPE(length = lbot[2].val) != INT) ! 798: { lbot[2].val = errorh1(Vermisc,"substringn: not integer length ", ! 799: nil, TRUE,0,length); ! 800: } ! 801: reallen = length->i; ! 802: } ! 803: else reallen = -1; ! 804: ! 805: len = strlen(name); ! 806: ind = index->i; ! 807: if(ind < 0) ind = len + 1 + ind; ! 808: if( ind < 1 || ind > len) return(nil); ! 809: ! 810: if(reallen == 0) ! 811: return((lispval)inewint(*(name + ind - 1))); ! 812: else { ! 813: char *pnt = name + ind - 1; ! 814: char *last = name + len -1; ! 815: lispval cur,start; ! 816: ! 817: protect(cur = start = newdot()); ! 818: cur->d.car = inewint(*pnt); ! 819: while(++pnt <= last && --reallen != 0) ! 820: { ! 821: cur->d.cdr = newdot(); ! 822: cur = cur->d.cdr; ! 823: cur->d.car = inewint(*pnt); ! 824: } ! 825: Restorestack(); ! 826: return(start); ! 827: } ! 828: ! 829: } ! 830: ! 831: lispval Ipurcopy(); ! 832: ! 833: ! 834: lispval ! 835: Lpurcopy() ! 836: { ! 837: chkarg(1,"purcopy"); ! 838: return(Ipurcopy(lbot[0].val)); ! 839: } ! 840: ! 841: lispval ! 842: Ipurcopy(handy) ! 843: lispval handy; ! 844: { ! 845: extern int *beginsweep; ! 846: register lispval retv, curv, lv; ! 847: int i,size; ! 848: ! 849: switch(TYPE(handy)) { ! 850: ! 851: case DTPR: ! 852: retv = curv = pnewdot(); ! 853: lv = handy; ! 854: while(TRUE) ! 855: { ! 856: curv->d.car = Ipurcopy(lv->d.car); ! 857: if(TYPE(lv = lv->d.cdr) == DTPR) ! 858: { ! 859: curv->d.cdr = pnewdot(); ! 860: curv = curv->d.cdr; ! 861: } ! 862: else { ! 863: curv->d.cdr = Ipurcopy(lv); ! 864: break; ! 865: } ! 866: } ! 867: return(retv); ! 868: ! 869: case SDOT: ! 870: retv = curv = pnewsdot(); ! 871: lv = handy; ! 872: while(TRUE) ! 873: { ! 874: curv->s.I = lv->s.I; ! 875: if(lv->s.CDR == (lispval) 0) break; ! 876: lv = lv->s.CDR; ! 877: curv->s.CDR = pnewdot(); ! 878: curv = curv->s.CDR; ! 879: } ! 880: curv->s.CDR = 0; ! 881: return(retv); ! 882: ! 883: case INT: ! 884: if((int *)handy < beginsweep) return(handy); ! 885: retv = pnewint(); ! 886: retv->i = handy->i; ! 887: return(retv); ! 888: ! 889: case DOUB: ! 890: retv = pnewdoub(); ! 891: retv->r = handy->r; ! 892: return(retv); ! 893: ! 894: case HUNK2: ! 895: i = 0; ! 896: goto hunkit; ! 897: ! 898: case HUNK4: ! 899: i = 1; ! 900: goto hunkit; ! 901: ! 902: case HUNK8: ! 903: i = 2; ! 904: goto hunkit; ! 905: ! 906: case HUNK16: ! 907: i = 3; ! 908: goto hunkit; ! 909: ! 910: case HUNK32: ! 911: i = 4; ! 912: goto hunkit; ! 913: ! 914: case HUNK64: ! 915: i = 5; ! 916: goto hunkit; ! 917: ! 918: case HUNK128: ! 919: i = 6; ! 920: ! 921: hunkit: ! 922: retv = pnewhunk(i); ! 923: size = 2 << i ; /* number of elements to copy over */ ! 924: for( i = 0; i < size ; i++) ! 925: { ! 926: retv->h.hunk[i] = Ipurcopy(handy->h.hunk[i]); ! 927: } ! 928: return(retv); ! 929: ! 930: ! 931: ! 932: case STRNG: ! 933: #ifdef GCSTRINGS ! 934: { extern char purepage[]; ! 935: ! 936: if(purepage[((int)handy)>>9]==0) ! 937: return((lispval)pinewstr((char *)handy));} ! 938: ! 939: #endif ! 940: case ATOM: ! 941: case BCD: ! 942: case PORT: ! 943: return(handy); /* We don't want to purcopy these, yet ! 944: * it won't hurt if we don't mark them ! 945: * since they either aren't swept or ! 946: * will be marked in a special way ! 947: */ ! 948: case ARRAY: ! 949: error("purcopy: can't purcopy array structures",FALSE); ! 950: ! 951: default: ! 952: error(" bad type to purcopy ",FALSE); ! 953: /* NOTREACHED */ ! 954: } ! 955: } ! 956: ! 957: /* ! 958: * Lpurep returns t if the given arg is in pure space ! 959: */ ! 960: lispval ! 961: Lpurep() ! 962: { ! 963: lispval Ipurep(); ! 964: ! 965: chkarg(1,"purep"); ! 966: return(Ipurep(lbot->val)); ! 967: } ! 968: ! 969: ! 970: ! 971: /* vector functions */ ! 972: lispval newvec(), nveci(), Inewvector(); ! 973: ! 974: /* vector creation and initialization functions */ ! 975: lispval ! 976: Lnvec() ! 977: { ! 978: return(Inewvector(3)); ! 979: } ! 980: ! 981: lispval ! 982: Lnvecb() ! 983: { ! 984: return(Inewvector(0)); ! 985: } ! 986: ! 987: lispval ! 988: Lnvecw() ! 989: { ! 990: return(Inewvector(1)); ! 991: } ! 992: ! 993: lispval ! 994: Lnvecl() ! 995: { ! 996: return(Inewvector(2)); ! 997: } ! 998: ! 999: /* ! 1000: * (new-vector 'x_size ['g_fill] ['g_prop]) ! 1001: * class = 0: byte \ ! 1002: * = 1: word > immediate ! 1003: * = 2: long / ! 1004: * = 3: long ! 1005: */ ! 1006: lispval ! 1007: Inewvector(class) ! 1008: { ! 1009: register int i; ! 1010: register lispval handy; ! 1011: register lispval *handy2; ! 1012: char *chandy; ! 1013: short *whandy; ! 1014: long *lhandy; ! 1015: lispval sizearg, fillarg, proparg; ! 1016: int size, vsize; ! 1017: ! 1018: fillarg = proparg = nil; ! 1019: ! 1020: switch(np-lbot) { ! 1021: case 3: proparg = lbot[2].val; ! 1022: case 2: fillarg = lbot[1].val; ! 1023: case 1: sizearg = lbot[0].val; ! 1024: break; ! 1025: default: argerr("new-vector"); ! 1026: } ! 1027: ! 1028: while((TYPE(sizearg) != INT) || sizearg->i < 0) ! 1029: sizearg = errorh1(Vermisc,"new-vector: bad size for vector ",nil, ! 1030: TRUE,0,sizearg); ! 1031: size = sizearg->i; ! 1032: switch(class) ! 1033: { ! 1034: case 0: vsize = size * sizeof(char); ! 1035: break; ! 1036: case 1: vsize = size * sizeof(short); ! 1037: break; ! 1038: default: vsize = size * sizeof(long); ! 1039: break; ! 1040: } ! 1041: ! 1042: if(class != 3) handy = nveci(vsize); ! 1043: else handy = newvec(vsize); ! 1044: ! 1045: switch(class) ! 1046: { ! 1047: case 0: chandy = (char *)handy; ! 1048: for(i = 0 ; i < size ; i++) *chandy++ = (char) (fillarg->i); ! 1049: break; ! 1050: ! 1051: case 1: whandy = (short *)handy; ! 1052: for(i = 0 ; i < size ; i++) *whandy++ = (short) (fillarg->i); ! 1053: break; ! 1054: ! 1055: case 2: lhandy = (long *)handy; ! 1056: for(i = 0 ; i < size ; i++) *lhandy++ = (fillarg->i); ! 1057: break; ! 1058: ! 1059: case 3: handy2 = (lispval *)handy; ! 1060: for(i = 0 ; i < size ; i++) *handy2++ = fillarg; ! 1061: break; ! 1062: } ! 1063: handy->v.vector[-1] = proparg; ! 1064: return(handy); ! 1065: } ! 1066: ! 1067: lispval ! 1068: Lvectorp() ! 1069: { ! 1070: chkarg(1,"vectorp"); ! 1071: if(TYPE(lbot->val) == VECTOR) return(tatom); ! 1072: else return(nil); ! 1073: } ! 1074: ! 1075: lispval ! 1076: Lpvp() ! 1077: { ! 1078: chkarg(1,"vectorip"); ! 1079: if(TYPE(lbot->val) == VECTORI) return(tatom); ! 1080: else return(nil); ! 1081: } ! 1082: ! 1083: /* ! 1084: * int:vref vector[i] index class ! 1085: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long ! 1086: */ ! 1087: lispval ! 1088: LIvref() ! 1089: { ! 1090: register lispval vect; ! 1091: register int index; ! 1092: int class; ! 1093: ! 1094: chkarg(3,"int:vref"); ! 1095: vect = lbot[0].val; ! 1096: index = lbot[1].val->i; ! 1097: class = lbot[2].val->i; ! 1098: switch(class) ! 1099: { ! 1100: case 0: return(inewint(vect->vb.vectorb[index])); ! 1101: case 1: return(inewint(vect->vw.vectorw[index])); ! 1102: case 2: return(inewint(vect->vl.vectorl[index])); ! 1103: case 3: return(vect->v.vector[index]); ! 1104: } ! 1105: error("int:vref: impossible class detected",FALSE); ! 1106: /* NOTREACHED */ ! 1107: } ! 1108: ! 1109: /* ! 1110: * int:vset vector[i] index value class ! 1111: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long ! 1112: */ ! 1113: lispval ! 1114: LIvset() ! 1115: { ! 1116: register lispval vect,value; ! 1117: register int index; ! 1118: int class; ! 1119: ! 1120: chkarg(4,"int:vset"); ! 1121: vect = lbot[0].val; ! 1122: index = lbot[1].val->i; ! 1123: value = lbot[2].val; ! 1124: class = lbot[3].val->i; ! 1125: switch(class) ! 1126: { ! 1127: case 0: vect->vb.vectorb[index] = (char)value->i; ! 1128: break; ! 1129: case 1: vect->vw.vectorw[index] = (short)value->i; ! 1130: break; ! 1131: case 2: vect->vl.vectorl[index] = value->i; ! 1132: break; ! 1133: case 3: vect->v.vector[index] = value; ! 1134: break; ! 1135: } ! 1136: return(value); ! 1137: } ! 1138: ! 1139: /* ! 1140: * LIvsize == (int:vsize 'vector 'x_shift) ! 1141: * return the vsize field of the vector shifted right by x_shift ! 1142: */ ! 1143: lispval ! 1144: LIvsize() ! 1145: { ! 1146: int typ; ! 1147: ! 1148: chkarg(2,"int:vsize"); ! 1149: return(inewint((lbot[0].val->vl.vectorl[VSizeOff]) >> lbot[1].val->i)); ! 1150: } ! 1151: ! 1152: lispval ! 1153: Lvprop() ! 1154: { ! 1155: int typ; ! 1156: chkarg(1,"vprop"); ! 1157: ! 1158: if(((typ = TYPE(lbot->val)) != VECTOR) && (typ != VECTORI)) ! 1159: errorh1(Vermisc,"vprop: non vector argument: ", nil, FALSE,0, ! 1160: lbot->val); ! 1161: return(lbot[0].val->v.vector[VPropOff]); ! 1162: } ! 1163: ! 1164: ! 1165: lispval ! 1166: Lvsp() ! 1167: { ! 1168: int typ; ! 1169: lispval vector, property; ! 1170: chkarg(2,"vsetprop"); ! 1171: ! 1172: vector = lbot->val; ! 1173: property = lbot[1].val; ! 1174: typ = TYPE(vector); ! 1175: ! 1176: if(typ != VECTOR && typ !=VECTORI) ! 1177: errorh1(Vermisc,"vsetprop: non vector argument: ", ! 1178: nil,FALSE,0,vector); ! 1179: vector->v.vector[VPropOff] = property; ! 1180: return(property); ! 1181: } ! 1182: ! 1183: ! 1184: /* vecequal ! 1185: * check if the two vector arguments are 'equal' ! 1186: * this is called by equal which has already checked that ! 1187: * the arguments are vector ! 1188: */ ! 1189: vecequal(v,w) ! 1190: lispval v,w; ! 1191: { ! 1192: int i; ! 1193: lispval vv, ww, ret; ! 1194: int vsize = (int) v->v.vector[VSizeOff]; ! 1195: int wsize = (int) w->v.vector[VSizeOff]; ! 1196: struct argent *oldlbot = lbot; ! 1197: lispval Lequal(); ! 1198: ! 1199: if(vsize != wsize) return(FALSE); ! 1200: ! 1201: vsize /= sizeof(int); /* determine number of entries */ ! 1202: ! 1203: for(i = 0 ; i < vsize ; i++) ! 1204: { ! 1205: vv = v->v.vector[i]; ! 1206: ww = w->v.vector[i]; ! 1207: /* avoid calling equal if they are eq */ ! 1208: if(vv != ww) ! 1209: { ! 1210: lbot = np; ! 1211: protect(vv); ! 1212: protect(ww); ! 1213: ret = Lequal(); ! 1214: np = lbot; ! 1215: lbot = oldlbot; ! 1216: if(ret == nil) return(FALSE); ! 1217: } ! 1218: } ! 1219: return(TRUE); ! 1220: } ! 1221: ! 1222: /* veciequal ! 1223: * check if the two vectori arguments are 'equal' ! 1224: * this is called by equal which has already checked that ! 1225: * the arguments are vector ! 1226: * Note: this would run faster if we did as many 'longword' ! 1227: * comparisons as possible and then did byte comparisons. ! 1228: * or if we used pointers instead of indexing. ! 1229: */ ! 1230: veciequal(v,w) ! 1231: lispval v,w; ! 1232: { ! 1233: char vv, ww; ! 1234: int i; ! 1235: int vsize = (int) v->v.vector[VSizeOff]; ! 1236: int wsize = (int) w->v.vector[VSizeOff]; ! 1237: ! 1238: if(vsize != wsize) return(FALSE); ! 1239: ! 1240: ! 1241: for(i = 0 ; i < vsize ; i++) ! 1242: { ! 1243: if(v->vb.vectorb[i] != w->vb.vectorb[i]) return(FALSE); ! 1244: } ! 1245: return(TRUE); ! 1246: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.