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: }

Defined functions

Ibalmod defined in line 506; used 2 times
Imath defined in line 22; used 7 times
Inewvector defined in line 1043; used 5 times
Ipurcopy defined in line 878; used 7 times
LIvref defined in line 1128; never used
LIvset defined in line 1166; never used
LIvsize defined in line 1208; never used
LMakhunk defined in line 272; never used
Lacos defined in line 57; never used
Lasin defined in line 52; never used
Latan defined in line 79; never used
Lcharindex defined in line 844; never used
Lcos defined in line 47; never used
Lcprintf defined in line 624; never used
Lctcherr defined in line 209; used 2 times
Lcxr defined in line 303; never used
Lexp defined in line 66; never used
Lfileopen defined in line 466; never used
Lfseek defined in line 145; never used
Lhashst defined in line 176; never used
Lhtol defined in line 426; never used
Lhunksize defined in line 399; never used
Llog defined in line 71; never used
Llsh defined in line 578; never used
Lmakunb defined in line 132; never used
Lnvec defined in line 1012; never used
Lnvecb defined in line 1018; never used
Lnvecl defined in line 1030; never used
Lnvecw defined in line 1024; never used
Lprobef defined in line 716; never used
Lpurcopy defined in line 871; never used
Lpurep defined in line 997; never used
Lpvp defined in line 1112; never used
Lrandom defined in line 115; never used
Lrplcx defined in line 337; never used
Lsin defined in line 42; never used
Lsprintf defined in line 666; never used
Lsqrt defined in line 62; never used
Lsstrn defined in line 776; never used
LstarMod defined in line 572; never used
Lstarinvmod defined in line 561; never used
Lstarrpx defined in line 372; never used
Lsubstring defined in line 728; never used
Lvectorp defined in line 1104; never used
Lvprop defined in line 1217; never used
Lvsp defined in line 1230; never used
bndchk defined in line 609; never used
invmod defined in line 535; used 1 times
vecequal defined in line 1254; used 1 times
veciequal defined in line 1295; used 1 times

Defined variables

rcsid defined in line 2; never used

Defined macros

index defined in line 842; used 31 times
Last modified: 1985-08-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2844
Valid CSS Valid XHTML 1.0 Strict