|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: lam8.c,v 1.16 85/03/24 11:04:31 sklower Exp $"; ! 4: #endif ! 5: ! 6: /* -[Thu Sep 29 22:24:10 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: Lrplcx() ! 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(P(port)); ! 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: ! 832: /* ! 833: * (character-index 'string 'char) ! 834: * return the index of char in the string. ! 835: * return nil if not present ! 836: * char can be a fixnum (representing a character) ! 837: * a symbol or string (in which case the first char is used) ! 838: * ! 839: */ ! 840: ! 841: #if os_unix_ts ! 842: #define index strchr ! 843: #endif ! 844: lispval ! 845: Lcharindex() ! 846: { ! 847: register char *string; ! 848: register char ch; ! 849: char *str2; ! 850: ! 851: chkarg(2,"character-index"); ! 852: ! 853: ! 854: string = (char *)verify(lbot[0].val,"character-index: non symbol or string arg "); ! 855: if(TYPE(lbot[1].val) == INT) ! 856: ch = (char) lbot[1].val->i; ! 857: else { ! 858: str2 = (char *) verify(lbot[1].val,"character-index: bad first argument "); ! 859: ch = *str2; /* grab the first character */ ! 860: } ! 861: ! 862: if((str2 = (char *) index(string,ch)) == 0) return(nil); /* not there */ ! 863: /* return 1-based index of character */ ! 864: return(inewint(str2-string+1)); ! 865: } ! 866: ! 867: ! 868: lispval Ipurcopy(); ! 869: ! 870: ! 871: lispval ! 872: Lpurcopy() ! 873: { ! 874: chkarg(1,"purcopy"); ! 875: return(Ipurcopy(lbot[0].val)); ! 876: } ! 877: ! 878: lispval ! 879: Ipurcopy(handy) ! 880: lispval handy; ! 881: { ! 882: extern int *beginsweep; ! 883: register lispval retv, curv, lv; ! 884: int i,size; ! 885: ! 886: switch(TYPE(handy)) { ! 887: ! 888: case DTPR: ! 889: retv = curv = pnewdot(); ! 890: lv = handy; ! 891: while(TRUE) ! 892: { ! 893: curv->d.car = Ipurcopy(lv->d.car); ! 894: if(TYPE(lv = lv->d.cdr) == DTPR) ! 895: { ! 896: curv->d.cdr = pnewdot(); ! 897: curv = curv->d.cdr; ! 898: } ! 899: else { ! 900: curv->d.cdr = Ipurcopy(lv); ! 901: break; ! 902: } ! 903: } ! 904: return(retv); ! 905: ! 906: case SDOT: ! 907: retv = curv = pnewsdot(); ! 908: lv = handy; ! 909: while(TRUE) ! 910: { ! 911: curv->s.I = lv->s.I; ! 912: if(lv->s.CDR == (lispval) 0) break; ! 913: lv = lv->s.CDR; ! 914: curv->s.CDR = pnewdot(); ! 915: curv = curv->s.CDR; ! 916: } ! 917: curv->s.CDR = 0; ! 918: return(retv); ! 919: ! 920: case INT: ! 921: if((int *)handy < beginsweep) return(handy); ! 922: retv = pnewint(); ! 923: retv->i = handy->i; ! 924: return(retv); ! 925: ! 926: case DOUB: ! 927: retv = pnewdb(); ! 928: retv->r = handy->r; ! 929: return(retv); ! 930: ! 931: case HUNK2: ! 932: i = 0; ! 933: goto hunkit; ! 934: ! 935: case HUNK4: ! 936: i = 1; ! 937: goto hunkit; ! 938: ! 939: case HUNK8: ! 940: i = 2; ! 941: goto hunkit; ! 942: ! 943: case HUNK16: ! 944: i = 3; ! 945: goto hunkit; ! 946: ! 947: case HUNK32: ! 948: i = 4; ! 949: goto hunkit; ! 950: ! 951: case HUNK64: ! 952: i = 5; ! 953: goto hunkit; ! 954: ! 955: case HUNK128: ! 956: i = 6; ! 957: ! 958: hunkit: ! 959: retv = pnewhunk(i); ! 960: size = 2 << i ; /* number of elements to copy over */ ! 961: for( i = 0; i < size ; i++) ! 962: { ! 963: retv->h.hunk[i] = Ipurcopy(handy->h.hunk[i]); ! 964: } ! 965: return(retv); ! 966: ! 967: ! 968: ! 969: case STRNG: ! 970: #ifdef GCSTRINGS ! 971: { extern char purepage[]; ! 972: ! 973: if(purepage[((int)handy)>>9]==0) ! 974: return((lispval)pinewstr((char *)handy));} ! 975: ! 976: #endif ! 977: case ATOM: ! 978: case BCD: ! 979: case PORT: ! 980: return(handy); /* We don't want to purcopy these, yet ! 981: * it won't hurt if we don't mark them ! 982: * since they either aren't swept or ! 983: * will be marked in a special way ! 984: */ ! 985: case ARRAY: ! 986: error("purcopy: can't purcopy array structures",FALSE); ! 987: ! 988: default: ! 989: error(" bad type to purcopy ",FALSE); ! 990: /* NOTREACHED */ ! 991: } ! 992: } ! 993: ! 994: /* ! 995: * Lpurep returns t if the given arg is in pure space ! 996: */ ! 997: lispval ! 998: Lpurep() ! 999: { ! 1000: lispval Ipurep(); ! 1001: ! 1002: chkarg(1,"purep"); ! 1003: return(Ipurep(lbot->val)); ! 1004: } ! 1005: ! 1006: ! 1007: ! 1008: /* vector functions */ ! 1009: lispval newvec(), nveci(), Inewvector(); ! 1010: ! 1011: /* vector creation and initialization functions */ ! 1012: lispval ! 1013: Lnvec() ! 1014: { ! 1015: return(Inewvector(3)); ! 1016: } ! 1017: ! 1018: lispval ! 1019: Lnvecb() ! 1020: { ! 1021: return(Inewvector(0)); ! 1022: } ! 1023: ! 1024: lispval ! 1025: Lnvecw() ! 1026: { ! 1027: return(Inewvector(1)); ! 1028: } ! 1029: ! 1030: lispval ! 1031: Lnvecl() ! 1032: { ! 1033: return(Inewvector(2)); ! 1034: } ! 1035: ! 1036: /* ! 1037: * (new-vector 'x_size ['g_fill] ['g_prop]) ! 1038: * class = 0: byte \ ! 1039: * = 1: word > immediate ! 1040: * = 2: long / ! 1041: * = 3: long ! 1042: */ ! 1043: lispval ! 1044: Inewvector(class) ! 1045: { ! 1046: register int i; ! 1047: register lispval handy; ! 1048: register lispval *handy2; ! 1049: char *chandy; ! 1050: short *whandy; ! 1051: long *lhandy; ! 1052: lispval sizearg, fillarg, proparg; ! 1053: int size, vsize; ! 1054: ! 1055: fillarg = proparg = nil; ! 1056: ! 1057: switch(np-lbot) { ! 1058: case 3: proparg = lbot[2].val; ! 1059: case 2: fillarg = lbot[1].val; ! 1060: case 1: sizearg = lbot[0].val; ! 1061: break; ! 1062: default: argerr("new-vector"); ! 1063: } ! 1064: ! 1065: while((TYPE(sizearg) != INT) || sizearg->i < 0) ! 1066: sizearg = errorh1(Vermisc,"new-vector: bad size for vector ",nil, ! 1067: TRUE,0,sizearg); ! 1068: size = sizearg->i; ! 1069: switch(class) ! 1070: { ! 1071: case 0: vsize = size * sizeof(char); ! 1072: break; ! 1073: case 1: vsize = size * sizeof(short); ! 1074: break; ! 1075: default: vsize = size * sizeof(long); ! 1076: break; ! 1077: } ! 1078: ! 1079: if(class != 3) handy = nveci(vsize); ! 1080: else handy = newvec(vsize); ! 1081: ! 1082: switch(class) ! 1083: { ! 1084: case 0: chandy = (char *)handy; ! 1085: for(i = 0 ; i < size ; i++) *chandy++ = (char) (fillarg->i); ! 1086: break; ! 1087: ! 1088: case 1: whandy = (short *)handy; ! 1089: for(i = 0 ; i < size ; i++) *whandy++ = (short) (fillarg->i); ! 1090: break; ! 1091: ! 1092: case 2: lhandy = (long *)handy; ! 1093: for(i = 0 ; i < size ; i++) *lhandy++ = (fillarg->i); ! 1094: break; ! 1095: ! 1096: case 3: handy2 = (lispval *)handy; ! 1097: for(i = 0 ; i < size ; i++) *handy2++ = fillarg; ! 1098: break; ! 1099: } ! 1100: handy->v.vector[-1] = proparg; ! 1101: return(handy); ! 1102: } ! 1103: ! 1104: lispval ! 1105: Lvectorp() ! 1106: { ! 1107: chkarg(1,"vectorp"); ! 1108: if(TYPE(lbot->val) == VECTOR) return(tatom); ! 1109: else return(nil); ! 1110: } ! 1111: ! 1112: lispval ! 1113: Lpvp() ! 1114: { ! 1115: chkarg(1,"vectorip"); ! 1116: if(TYPE(lbot->val) == VECTORI) return(tatom); ! 1117: else return(nil); ! 1118: } ! 1119: ! 1120: /* ! 1121: * int:vref vector[i] index class ! 1122: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long ! 1123: * ! 1124: * also do C style dereferencing of pointers. This is a temporary ! 1125: * hack until we decide if we can live without it: ! 1126: * class = 4: char, 5: short, 6: long, 7: float, 8: double ! 1127: */ ! 1128: lispval ! 1129: LIvref() ! 1130: { ! 1131: register lispval vect; ! 1132: register int index; ! 1133: int class; ! 1134: double value; ! 1135: ! 1136: chkarg(3,"int:vref"); ! 1137: vect = lbot[0].val; ! 1138: index = lbot[1].val->i; ! 1139: class = lbot[2].val->i; ! 1140: switch(class) ! 1141: { ! 1142: case 0: return(inewint(vect->vb.vectorb[index])); ! 1143: case 1: return(inewint(vect->vw.vectorw[index])); ! 1144: case 2: return(inewint(vect->vl.vectorl[index])); ! 1145: case 3: return(vect->v.vector[index]); ! 1146: case 4: return(inewint(*(char *)(vect->i+index))); ! 1147: case 5: return(inewint(*(short *)(vect->i+index))); ! 1148: case 6: return(inewint(*(long *)(vect->i+index))); ! 1149: case 7: value = *(float *) (vect->i+index); ! 1150: vect = newdoub(); ! 1151: vect->r = value; ! 1152: return(vect); ! 1153: case 8: value = *(double *) (vect->i+index); ! 1154: vect = newdoub(); ! 1155: vect->r = value; ! 1156: return(vect); ! 1157: } ! 1158: error("int:vref: impossible class detected",FALSE); ! 1159: /* NOTREACHED */ ! 1160: } ! 1161: ! 1162: /* ! 1163: * int:vset vector[i] index value class ! 1164: * class = 0: byte immed, 1: word immed, 2: long immed, 3: long ! 1165: */ ! 1166: lispval ! 1167: LIvset() ! 1168: { ! 1169: register lispval vect,value; ! 1170: register int index; ! 1171: int class; ! 1172: ! 1173: chkarg(4,"int:vset"); ! 1174: vect = lbot[0].val; ! 1175: index = lbot[1].val->i; ! 1176: value = lbot[2].val; ! 1177: class = lbot[3].val->i; ! 1178: switch(class) ! 1179: { ! 1180: case 0: vect->vb.vectorb[index] = (char)value->i; ! 1181: break; ! 1182: case 1: vect->vw.vectorw[index] = (short)value->i; ! 1183: break; ! 1184: case 2: vect->vl.vectorl[index] = value->i; ! 1185: break; ! 1186: case 3: vect->v.vector[index] = value; ! 1187: break; ! 1188: case 4: *(char *) (vect->i+index) = value->i; ! 1189: break; ! 1190: case 5: *(short *) (vect->i+index) = value->i; ! 1191: break; ! 1192: case 6: *(long *) (vect->i+index) = value->i; ! 1193: break; ! 1194: case 7: *(float *) (vect->i+index) = value->r; ! 1195: break; ! 1196: case 8: *(double *) (vect->i+index) = value->r; ! 1197: break; ! 1198: default: ! 1199: error("int:vref: impossible class detected",FALSE); ! 1200: } ! 1201: return(value); ! 1202: } ! 1203: ! 1204: /* ! 1205: * LIvsize == (int:vsize 'vector 'x_shift) ! 1206: * return the vsize field of the vector shifted right by x_shift ! 1207: */ ! 1208: lispval ! 1209: LIvsize() ! 1210: { ! 1211: int typ; ! 1212: ! 1213: chkarg(2,"int:vsize"); ! 1214: return(inewint((lbot[0].val->vl.vectorl[VSizeOff]) >> lbot[1].val->i)); ! 1215: } ! 1216: ! 1217: lispval ! 1218: Lvprop() ! 1219: { ! 1220: int typ; ! 1221: chkarg(1,"vprop"); ! 1222: ! 1223: if(((typ = TYPE(lbot->val)) != VECTOR) && (typ != VECTORI)) ! 1224: errorh1(Vermisc,"vprop: non vector argument: ", nil, FALSE,0, ! 1225: lbot->val); ! 1226: return(lbot[0].val->v.vector[VPropOff]); ! 1227: } ! 1228: ! 1229: ! 1230: lispval ! 1231: Lvsp() ! 1232: { ! 1233: int typ; ! 1234: lispval vector, property; ! 1235: chkarg(2,"vsetprop"); ! 1236: ! 1237: vector = lbot->val; ! 1238: property = lbot[1].val; ! 1239: typ = TYPE(vector); ! 1240: ! 1241: if(typ != VECTOR && typ !=VECTORI) ! 1242: errorh1(Vermisc,"vsetprop: non vector argument: ", ! 1243: nil,FALSE,0,vector); ! 1244: vector->v.vector[VPropOff] = property; ! 1245: return(property); ! 1246: } ! 1247: ! 1248: ! 1249: /* vecequal ! 1250: * check if the two vector arguments are 'equal' ! 1251: * this is called by equal which has already checked that ! 1252: * the arguments are vector ! 1253: */ ! 1254: vecequal(v,w) ! 1255: lispval v,w; ! 1256: { ! 1257: int i; ! 1258: lispval vv, ww, ret; ! 1259: int vsize = (int) v->v.vector[VSizeOff]; ! 1260: int wsize = (int) w->v.vector[VSizeOff]; ! 1261: struct argent *oldlbot = lbot; ! 1262: lispval Lequal(); ! 1263: ! 1264: if(vsize != wsize) return(FALSE); ! 1265: ! 1266: vsize /= sizeof(int); /* determine number of entries */ ! 1267: ! 1268: for(i = 0 ; i < vsize ; i++) ! 1269: { ! 1270: vv = v->v.vector[i]; ! 1271: ww = w->v.vector[i]; ! 1272: /* avoid calling equal if they are eq */ ! 1273: if(vv != ww) ! 1274: { ! 1275: lbot = np; ! 1276: protect(vv); ! 1277: protect(ww); ! 1278: ret = Lequal(); ! 1279: np = lbot; ! 1280: lbot = oldlbot; ! 1281: if(ret == nil) return(FALSE); ! 1282: } ! 1283: } ! 1284: return(TRUE); ! 1285: } ! 1286: ! 1287: /* veciequal ! 1288: * check if the two vectori arguments are 'equal' ! 1289: * this is called by equal which has already checked that ! 1290: * the arguments are vector ! 1291: * Note: this would run faster if we did as many 'longword' ! 1292: * comparisons as possible and then did byte comparisons. ! 1293: * or if we used pointers instead of indexing. ! 1294: */ ! 1295: veciequal(v,w) ! 1296: lispval v,w; ! 1297: { ! 1298: char vv, ww; ! 1299: int i; ! 1300: int vsize = (int) v->v.vector[VSizeOff]; ! 1301: int wsize = (int) w->v.vector[VSizeOff]; ! 1302: ! 1303: if(vsize != wsize) return(FALSE); ! 1304: ! 1305: ! 1306: for(i = 0 ; i < vsize ; i++) ! 1307: { ! 1308: if(v->vb.vectorb[i] != w->vb.vectorb[i]) return(FALSE); ! 1309: } ! 1310: return(TRUE); ! 1311: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.