|
|
1.1 root 1: static char *sccsid = "@(#)lam8.c 34.5 11/7/80";
2:
3: #include "global.h"
4: #include <sys/types.h>
5: #include <pagsiz.h>
6: #include "naout.h"
7:
8: /* various functions from the c math library */
9: double sin(),cos(),asin(),acos(),atan2(),sqrt(), log(), exp();
10: extern int current;
11:
12: lispval Imath(func)
13: double (*func)();
14: {
15: register lispval handy;
16: register double res;
17: chkarg(1,"Math functions");
18:
19: switch(TYPE(handy=lbot->val)) {
20: case INT: res = func((double)handy->i);
21: break;
22:
23: case DOUB: res = func(handy->r);
24: break;
25:
26: default: error("Non fixnum or flonum to math function",FALSE);
27: }
28: handy = newdoub();
29: handy->r = res;
30: return(handy);
31: }
32: lispval Lsin()
33: {
34: return(Imath(sin));
35: }
36:
37: lispval Lcos()
38: {
39: return(Imath(cos));
40: }
41:
42: lispval Lasin()
43: {
44: return(Imath(asin));
45: }
46:
47: lispval Lacos()
48: {
49: return(Imath(acos));
50: }
51:
52: lispval Lsqrt()
53: {
54: return(Imath(sqrt));
55: }
56: lispval Lexp()
57: {
58: return(Imath(exp));
59: }
60:
61: lispval Llog()
62: {
63: return(Imath(log));
64: }
65:
66: /* although we call this atan, it is really atan2 to the c-world,
67: that is, it takes two args
68: */
69: lispval Latan()
70: {
71: register lispval arg;
72: register double arg1v;
73: register double res;
74: chkarg(2,"arctan");
75:
76: switch(TYPE(arg=lbot->val)) {
77:
78: case INT: arg1v = (double) arg->i;
79: break;
80:
81: case DOUB: arg1v = arg->r;
82: break;
83:
84: default: error("Non fixnum or flonum arg to atan2",FALSE);
85: }
86:
87: switch(TYPE(arg = (lbot+1)->val)) {
88:
89: case INT: res = atan2(arg1v,(double) arg->i);
90: break;
91:
92: case DOUB: res = atan2(arg1v, arg->r);
93: break;
94:
95: default: error("Non fixnum or flonum to atan2",FALSE);
96: }
97: arg = newdoub();
98: arg->r = res;
99: return(arg);
100: }
101:
102: /* (random) returns a fixnum in the range -2**30 to 2**30 -1
103: (random fixnum) returns a fixnum in the range 0 to fixnum-1
104: */
105: lispval
106: Lrandom()
107: {
108: register int curval;
109: float pow();
110:
111: curval = rand(); /* get numb from 0 to 2**31-1 */
112:
113: if(np==lbot) return(inewint(curval-(int)pow((double)2,(double)30)));
114:
115: if((TYPE(lbot->val) != INT)
116: || (lbot->val->i <= 0)) errorh(Vermisc,"random: non fixnum arg:",
117: nil, FALSE, 0, lbot->val);
118:
119: return(inewint(curval % lbot->val->i ));
120:
121: }
122: lispval
123: Lmakunb()
124: {
125: register lispval work;
126:
127: chkarg(1,"makunbound");
128: work = lbot->val;
129: if(work==nil || (TYPE(work)!=ATOM))
130: return(work);
131: work->a.clb = CNIL;
132: return(work);
133: }
134: lispval
135: Lpolyev()
136: {
137: register int count;
138: register double *handy, *base;
139: register struct argent *argp, *lbot, *np;
140: lispval result; int type;
141:
142: count = 2 * (((int) np) - (int) lbot);
143: if(count == 0)
144: return(inewint(0));
145: if(count == 8)
146: return(lbot->val);
147: base = handy = (double *) alloca(count);
148: for(argp = lbot; argp < np; argp++) {
149: while((type = TYPE(argp->val))!=DOUB && type!=INT)
150: argp->val = (lispval) errorh(Vermisc,"%%machine-polyev:non-real arg",nil,TRUE,73,lbot,argp->val);
151: if(TYPE(argp->val)==INT) {
152: *handy++ = argp->val->i;
153: } else
154: *handy++ = argp->val->r;
155: }
156: count = count/sizeof(double) - 2;
157: asm("polyd (r9),r11,8(r9)");
158: asm("movd r0,(r9)");
159: result = newdoub();
160: result->r = *base;
161: return(result);
162: }
163: typedef struct doub {
164: unsigned short f1:7,expt:8,sign:1;
165: unsigned short f2,f3p1:14,f3p2:2,f4;
166: } *dp;
167:
168: typedef struct quad2 {
169: unsigned long g4:16,g3p1:14;
170: } *qp2;
171:
172: typedef struct quad1 {
173: unsigned long g3p2:2,g2:16,g1:7,hide:1;
174: } *qp1;
175:
176: static long workbuf[2];
177: static int exponent;
178: static Idebig()
179: {
180: register lispval work;
181: register dp rdp;
182: register qp1 rqp1;
183: register qp2 rqp2;
184: register struct argent *lbot,np;
185: workbuf[1] = workbuf[0] = 0;
186:
187: work = lbot->val; /* Unfold mantissa */
188: rqp2 = (qp2) workbuf + 1;
189: rqp1 = (qp1) workbuf;
190: rdp = (dp) work;
191: rqp2->g4 = rdp->f4;
192: rqp2->g3p1 = rdp->f3p1;
193: rqp1->g3p2 = rdp->f3p2;
194: rqp1->g2 = rdp->f2;
195: rqp1->g1 = rdp->f1;
196: rqp1->hide = 1;
197: if(rdp->sign) {
198: workbuf[0] = (- workbuf[0]);
199: if(workbuf[1] = (- workbuf[1]) & 0xC0000000)
200: workbuf[0]--;
201: }
202: /* calcuate exponent and adjustment */
203: exponent = -129 - 55 + (int) rdp->expt;
204: }
205: lispval
206: Lfdecom()
207: {
208: register lispval result, handy;
209: register dum1,dum2;
210: register struct argent *lbot,*np;
211:
212: chkarg(1,"Decompose-float");
213: while(TYPE(lbot->val)!=DOUB)
214: lbot->val = error("Decompose-float: Non-real argument",TRUE);
215: Idebig();
216: np++->val = result = handy = newdot();
217: handy->d.car = inewint(exponent);
218: handy = handy->d.cdr = newdot();
219: handy = handy->d.car = newsdot();
220: handy->s.I = workbuf[1];
221: handy = handy->s.CDR = newsdot();
222: handy->s.I = workbuf[0];
223: }
224:
225: lispval
226: Lfseek()
227: {
228: register lispval result, handy;
229: register dum1,dum2;
230: register struct argent *lbot,*np;
231:
232: FILE *f;
233: long disk_addr, offset, whence;
234: lispval retp;
235:
236: chkarg(3,"fseek"); /* Make sure there are three arguments*/
237:
238: f = lbot->val->p; /* Get first argument into f */
239: if (TYPE(lbot->val)!=PORT) /* Check type of first */
240: error("fseek: First argument must be a port.",FALSE);
241:
242: offset = lbot[1].val->i; /* Get second argument */
243: if (TYPE(lbot[1].val)!=INT)
244: error("fseek: Second argument must be an integer.",FALSE);
245:
246: whence = lbot[2].val->i; /* Get last arg */
247: if (TYPE(lbot[2].val)!=INT)
248: error("fseek: Third argument must be an integer.",FALSE);
249:
250: if (fseek(f, offset, whence) == -1)
251: error("fseek: Illegal parameters.",FALSE);
252:
253: retp = inewint(ftell(f));
254:
255: return((lispval) retp);
256: }
257:
258: /* function hashtabstat : return list of number of members in each bucket */
259: lispval Lhashst()
260: {
261: register lispval handy,cur;
262: register struct atom *pnt;
263: int i,cnt;
264: extern int hashtop;
265: snpand(3);
266:
267: handy = newdot();
268: protect(handy);
269: cur = handy;
270: for(i = 0; i < hashtop; i++)
271: {
272: pnt = hasht[i];
273: for(cnt = 0; pnt != (struct atom *) CNIL ; pnt=pnt->hshlnk , cnt++);
274: cur->d.cdr = newdot();
275: cur = cur->d.cdr;
276: cur->d.car = inewint(cnt);
277: }
278: cur->d.cdr = nil;
279: return(handy->d.cdr);
280: }
281:
282:
283: /* Lctcherr
284: this routine should only be called by the unwind protect simulation
285: lisp code
286: It is called after an unwind-protect frame has been entered and
287: evalated and we want to get on with the error or throw
288: We only handle the case where there are 0 to 2 extra arguments to the
289: error call.
290: */
291: lispval
292: Lctcherr()
293: {
294: register lispval handy;
295: lispval type,messg,valret,contuab,uniqid,datum1,datum2;
296: snpand(1);
297:
298: if(lbot-np==0) protect(nil);
299: if((handy = lbot->val) == nil) return(nil);
300:
301: if(handy->d.car == tatom)
302: { /* continuaing a throw */
303: Idothrow(handy->d.cdr->d.car, handy->d.cdr->d.cdr->d.car);
304: error("ctcherr: throw label gone!",FALSE);
305: }
306:
307: /* decode the arg list */
308: handy = handy->d.cdr;
309: type = handy->d.car;
310: handy = handy->d.cdr;
311: messg = handy->d.car;
312: handy = handy->d.cdr;
313: valret = handy->d.car;
314: handy = handy->d.cdr;
315: contuab = handy->d.car;
316: handy = handy->d.cdr;
317: uniqid = handy->d.car;
318: handy = handy->d.cdr;
319:
320: /* if not extra args */
321: if(handy == nil)
322: {
323: errorh(type,messg->a.pname,valret,contuab->i,uniqid->i);
324: }
325: datum1 = handy->d.car;
326: handy = handy->d.cdr;
327:
328: /* if one extra arg */
329: if(handy == nil)
330: {
331: errorh(type,messg->a.pname,valret,contuab->i,uniqid->i,datum1);
332: }
333:
334: /* if two or more extra args, just use first 2 */
335: datum2 = handy->d.car;
336: errorh(type,messg->a.pname,valret,contuab->i,uniqid->i,datum1,datum2);
337: }
338:
339: /*
340: * (*makhunk '<fixnum>)
341: * <fixnum>
342: * Create a hunk of size 2 . <fixnum> must be between 0 and 6.
343: *
344: */
345:
346: lispval
347: LMakhunk()
348: {
349: register int hsize, hcntr;
350: register lispval result;
351:
352: chkarg(1,"Makehunk");
353: if (TYPE(lbot->val)==INT)
354: {
355: hsize = lbot->val->i; /* size of hunk (0-6) */
356: if ((hsize >= 0) && (hsize <= 6))
357: {
358: result = newhunk(hsize);
359: hsize = 2 << hsize; /* size of hunk (2-128) */
360: for (hcntr = 0; hcntr < hsize; hcntr++)
361: result->h.hunk[hcntr] = hunkfree;
362: }
363: else
364: error("*makhunk: Illegal hunk size", FALSE);
365: return(result);
366: }
367: else
368: error("*makhunk: First arg must be an fixnum",FALSE);
369: }
370:
371: /*
372: * (cxr '<fixnum> '<hunk>)
373: * Returns the <fixnum>'th element of <hunk>
374: *
375: */
376: lispval
377: Lcxr()
378: {
379: register lispval temp;
380:
381: chkarg(2,"cxr");
382: if (TYPE(lbot->val)!=INT)
383: error("cxr: First arg must be a fixnum", FALSE);
384: else
385: {
386: if (! HUNKP(lbot[1].val))
387: error("cxr: Second arg must be a hunk", FALSE);
388: else
389: if ( (lbot->val->i >= 0) &&
390: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) )
391: {
392: temp = lbot[1].val->h.hunk[lbot->val->i];
393: if (temp != hunkfree)
394: return(temp);
395: else
396: error("cxr: Arg outside of hunk range",
397: FALSE);
398: }
399: else
400: error("cxr: Arg outside of hunk range", FALSE);
401: }
402: }
403:
404: /*
405: * (rplacx '<fixnum> '<hunk> '<expr>)
406: * Replaces the <fixnum>'th element of <hunk> with <expr>.
407: *
408: */
409: lispval
410: Lrplacx()
411: {
412: lispval *handy;
413: chkarg(3,"rplacx");
414: if (TYPE(lbot->val)!=INT)
415: error("rplacx: First arg must be a fixnum", FALSE);
416: else
417: {
418: if (! HUNKP(lbot[1].val))
419: error("rplacx: Second arg must be a hunk", FALSE);
420: else
421: {
422: if ( (lbot->val->i >= 0) &&
423: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) )
424: {
425: if (*(handy = &(lbot[1].val->h.hunk[lbot->val->i]))
426: != hunkfree)
427: *handy = lbot[2].val;
428: else
429: error("rplacx: Arg outside hunk range", FALSE);
430: }
431: else
432: error("rplacx: Arg outside hunk range", FALSE);
433: }
434: }
435: return(lbot[1].val);
436: }
437:
438: /*
439: * (*rplacx '<fixnum> '<hunk> '<expr>)
440: * Replaces the <fixnum>'th element of <hunk> with <expr>. This is the
441: * same as (rplacx ...) except with this function you can replace EMPTY's.
442: *
443: */
444: lispval
445: Lstarrpx()
446: {
447: chkarg(3,"*rplacx");
448: if (TYPE(lbot->val)!=INT)
449: error("*rplacx: First arg must be a fixnum", FALSE);
450: else
451: {
452: if (! HUNKP(lbot[1].val))
453: error("*rplacx: Second arg must be a hunk", FALSE);
454: else
455: {
456: if ( (lbot->val->i >= 0) &&
457: (lbot->val->i < (2 << HUNKSIZE(lbot[1].val))) )
458: lbot[1].val->h.hunk[lbot->val->i] = lbot[2].val;
459: else
460: error("*rplacx: Arg outside hunk range", FALSE);
461: }
462: }
463: return(lbot[1].val);
464: }
465:
466: /*
467: * (hunksize '<hunk>)
468: * Returns the size of <hunk>
469: *
470: */
471: lispval
472: Lhunksize()
473: {
474: register int size,i;
475:
476: chkarg(1,"hunksize");
477: if (HUNKP(lbot->val))
478: {
479: size = 2 << HUNKSIZE(lbot->val);
480: for (i = size-1; i >= 0; i--)
481: {
482: if (lbot->val->h.hunk[i] != hunkfree)
483: {
484: size = i + 1;
485: break;
486: }
487: }
488: return( inewint(size) );
489: }
490: else
491: error("hunksize: First argument must me a hunk", FALSE);
492: }
493:
494: /*
495: * (fileopen filename mode)
496: * open a file for read, write, or append the arguments can be either
497: * strings or atoms.
498: */
499: lispval
500: Lfileopen()
501: {
502: FILE *port;
503: register lispval name;
504: register lispval mode;
505: register char *namech;
506: register char *modech;
507: register struct argent *lbot, *np;
508: int typ;
509:
510: chkarg(2,"fileopen");
511: name = lbot->val;
512: mode = lbot[1].val;
513:
514: namech = (char *) verify(name,"fileopen:args must be atoms or strings");
515: modech = (char *) verify(mode,"fileopen:args must be atoms or strings");
516:
517: while (modech[0] != 'r' && modech[0] != 'w' && modech[0] != 'a')
518: {
519: mode = errorh(Vermisc,"Modes are only r, w, a.",nil,TRUE,31,(char *) 0);
520: modech = (char *) verify(mode,"fileopen:args must be atoms or strings");
521: }
522:
523: while ((port = fopen(namech, modech)) == NULL)
524: {
525: name = errorh(Vermisc,"Unable to open file.",nil,TRUE,31,name);
526: namech = (char *) verify(name,"fileopen:args must be atoms or strings");
527: }
528: /* xports is a FILE *, cc complains about adding pointers */
529:
530: return( (lispval) (xports + (port - _iob)));
531: }
532:
533: /*
534: * (*mod '<number> '<modulus>)
535: * This function returns <number> mod <modulus> (for balanced modulus).
536: * It is used in vaxima as a speed enhancement.
537: */
538: lispval
539: LstarMod()
540: {
541: register int mod_div_2, number, modulus;
542:
543: chkarg(2,"*mod");
544: if ((TYPE(lbot->val) == INT) && (TYPE(lbot[1].val) == INT))
545: {
546: modulus = lbot[1].val->i;
547: number = lbot->val->i % modulus;
548: mod_div_2 = modulus / 2;
549: if (number < 0)
550: {
551: if (number < (-mod_div_2))
552: number += modulus;
553: }
554: else
555: {
556: if (number > mod_div_2)
557: number -= modulus;
558: }
559: return( inewint(number) );
560: }
561: else
562: error("*mod: Arguments must be fixnums", FALSE);
563: }
564: lispval
565: Llsh()
566: {
567: register struct argent *mylbot = lbot;
568: int val,shift;
569:
570: chkarg(2,"lsh");
571: if((TYPE(mylbot->val) != INT) || (TYPE(mylbot[1].val) != INT))
572: errorh(Vermisc,
573: "Non ints to lsh",
574: nil,FALSE,0,mylbot->val,mylbot[1].val);
575: val = mylbot[0].val->i;
576: shift = mylbot[1].val->i;
577: if(shift < -32 || shift > 32)
578: return(inewint(0));
579: val = val << shift; /* do the shift */
580: if((val < 0) && (shift < 0))
581: { /* special case: the vax doesn't have a logical shift
582: instruction, so we must zero out the ones which
583: will propogate from the sign position
584: */
585: return(inewint ( val & ~(0x80000000 << (shift+1))));
586: }
587: else return( inewint(val));
588: }
589:
590: lispval
591: Lrot()
592: {
593: register rot,val; /* these must be the first registers */
594: register struct argent *mylbot = lbot;
595:
596: chkarg(2,"rot");
597: if((TYPE(mylbot->val) != INT) || (TYPE(mylbot[1].val) != INT))
598: errorh(Vermisc,
599: "Non ints to rot",
600: nil,FALSE,0,mylbot->val,mylbot[1].val);
601: val = mylbot[0].val->i;
602: rot = mylbot[1].val->i;
603: rot = rot % 32 ; /* bring it down below one byte in size */
604: asm(" rotl r11,r10,r10 "); /* rotate val by rot and put back in val */
605: return( inewint(val));
606: }
607:
608: /*----------------- vms routines to simulate dumplisp -------------------- */
609: #ifdef VMS
610:
611: extern char firstalloc[];
612: extern int lsbrkpnt;
613: extern char zfreespace[];
614: extern int end;
615:
616: #define roundup(a,b) (((a-1)|(b-1))+1)
617: lispval
618: Lsavelsp()
619: {
620: char *filnm;
621: int fp,i,num,start;
622:
623: chkarg(1,"savelisp");
624:
625: filnm = (char *) verify(lbot->val, "savelisp: non atom arg");
626: if((fp=creat(filnm,0666)) < 0)
627: errorh(Vermisc,"savelisp: can't open file",nil,FALSE,0,
628: lbot->val);
629: start = roundup((int)firstalloc,PAGSIZ);
630: num = roundup(((int)lsbrkpnt)-NBPG-start,PAGSIZ);
631: if((num = write(fp,start,num)) <= 0)
632: error("savelisp: write failed ",FALSE);
633: printf(" %x bytes written from %x to %x \n",num,start,start+num-1);
634: close(fp);
635: return(tatom);
636: }
637:
638: lispval
639: Lrestlsp()
640: {
641: char *filnm;
642: int fp,i,num,start;
643: extern int xcycle;
644:
645: chkarg(1,"restorelisp");
646:
647: filnm = (char *) verify(lbot->val,"restorelisp: non atom arg");
648: if((fp=open(filnm,0)) < 0)
649: errorh(Vermisc,"restorelisp: can't open file",nil,FALSE,0,
650: lbot->val);
651:
652: start = roundup((int)firstalloc,PAGSIZ);
653: if((num = vread(fp,start,((int)&end)-start)) <= 0)
654: error("restorelisp: read failed " ,FALSE);
655: printf(" %x bytes read into %x to %x\n",num,start,start+num-1);
656: xcycle = 0; /* indicate no saved pages to xsbrk */
657: close(fp);
658: bnp = orgbnp;
659: lbot = np = orgnp;
660: contval = 0;
661: reset(BRRETB); /* reset */
662: }
663: #endif
664:
665: /*----------------------------------------------------------- */
666:
667:
668: /* getaddress --
669: *
670: * (getaddress '|_entry1| 'fncname1 '|_entry2| 'fncname2 ...)
671: *
672: * binds value of symbol |_entry1| to function defition of atom fncname1, etc.
673: *
674: * returns fnc-binding of fncname1.
675: *
676: */
677:
678: lispval
679: Lgetaddress(){
680: register struct argent *mlbot = lbot;
681: register lispval work;
682: register int numberofargs, i;
683: register struct argent *lbot, *np;
684: char *gstab();
685: char ostabf[128];
686: struct nlist NTABLE[100];
687: lispval dispget();
688:
689: snpand(2);
690:
691: if(np-lbot == 2) protect(nil); /* allow 2 args */
692: numberofargs = (np - lbot)/3;
693: if(numberofargs * 3 != np-lbot)
694: error("getaddress: arguments must come in triples ",FALSE);
695:
696: for ( i=0; i<numberofargs; i++,mlbot += 3) {
697: NTABLE[i].n_value = 0;
698: mlbot[0].val = verify(mlbot[0].val,"Incorrect entry specification for binding");
699: NTABLE[i].n_un.n_name = (char *) mlbot[0].val;
700: while(TYPE(mlbot[1].val) != ATOM)
701: mlbot[1].val = errorh(Vermisc,
702: "Bad associated atom name for binding",
703: nil,TRUE,0,mlbot[1].val);
704: mlbot[2].val = dispget(mlbot[2].val,"getaddress: Incorrect discipline specification ",Vsubrou->a.pname);
705: }
706: NTABLE[(numberofargs)].n_un.n_name = "";
707: strcpyn(ostabf,gstab(),128);
708: if ( nlist(ostabf,NTABLE) == -1 ) {
709: errorh(Vermisc,"Getaddress: Bad file",nil,FALSE,0,inewstr(ostabf));
710: } else
711: for (i=0,mlbot=lbot+1; i<numberofargs; i++,mlbot+=3) {
712: if ( NTABLE[i].n_value == 0 )
713: fprintf(stderr,"Undefined symbol: %s\n",
714: NTABLE[i].n_un.n_name);
715: else {
716: work= newfunct();
717: work->bcd.entry = (lispval (*) ())NTABLE[i].n_value;
718: work->bcd.discipline = mlbot[1].val;
719: mlbot->val->a.fnbnd = work;
720: }
721: };
722: return(lbot[1].val->a.fnbnd);
723: };
724:
725: /* very temporary function to test the validity of the bind stack */
726:
727: bndchk()
728: {
729: register struct nament *npt;
730: register lispval in2;
731:
732: in2 = inewint(200);
733: for(npt=orgbnp; npt < bnp; npt++)
734: { if((int) npt->atm < (int) in2) asm(" halt ");
735: }
736: }
737:
738: /*
739: * formatted printer for lisp data
740: * use: (cprintf formatstring datum [port])
741: */
742: lispval
743: Lcprintf()
744: {
745: FILE *p;
746: char *fstrng;
747: lispval v;
748: if(np-lbot == 2) protect(nil); /* write to standard output port */
749: chkarg(3,"cprintf");
750:
751: fstrng = (char *)verify(lbot->val,"cprintf: first arg not string or symbol");
752:
753: p = okport(lbot[2].val,okport(Vpoport->a.clb,poport));
754:
755: switch(TYPE(v=lbot[1].val)) {
756:
757: case INT: fprintf(p,fstrng,v->i);
758: break;
759:
760: case DOUB: fprintf(p,fstrng,v->r);
761: break;
762:
763: case ATOM: fprintf(p,fstrng,v->a.pname);
764: break;
765:
766: case STRNG:fprintf(p,fstrng,v);
767: break;
768:
769: default: error("cprintf: Illegal second argument",FALSE);
770: };
771:
772: return(lbot[1].val);
773: }
774:
775: lispval
776: Lprobef()
777: {
778: char *name;
779: chkarg(1,"probef");
780:
781: name = (char *)verify(lbot->val,"probef: not symbol or string arg ");
782:
783: if(access(name,0) == 0) return(tatom);
784: else return(nil);
785: }
786:
787: lispval
788: Lsubstring()
789: { register char *name;
790: register lispval index,length;
791: int restofstring = FALSE;
792: int len,ind,reallen;
793: extern char strbuf[];
794:
795: switch (np-lbot)
796: {
797: case 2: restofstring = TRUE;
798: break;
799:
800: case 3: break;
801:
802: default: chkarg(3,"substring");
803: }
804:
805: name = (char *)verify(lbot[0].val,"substring: not symbol or string arg ");
806:
807: while (TYPE(index = lbot[1].val) != INT)
808: { lbot[1].val = errorh(Vermisc,"substring: non integer index ",nil,
809: TRUE,0,index);
810: }
811:
812: len = strlen(name);
813: ind = index->i;
814:
815: if(ind < 0) ind = len+1 + ind;
816:
817: if(ind < 1 || ind > len) return(nil); /*index out of bounds*/
818: if(restofstring) return((lispval)inewstr(name+ind-1));
819:
820: while (TYPE(length = lbot[2].val) != INT)
821: { lbot[2].val = errorh(Vermisc,"substring: not integer length ",nil,
822: TRUE,0,length);
823: }
824:
825: if((reallen = length->i ) < 0 || (reallen + ind) > len)
826: return((lispval)inewstr(name+ind-1));
827:
828: strncpy(strbuf,name+ind-1,reallen);
829: strbuf[reallen] = '\0';
830: return((lispval)newstr());
831: }
832:
833: lispval
834: Lsubstringn()
835: {
836: register char *name;
837: register int len,ind,reallen;
838: lispval index,length;
839: int restofstring = FALSE;
840: snpand(4);
841:
842: if((np-lbot) == 2) restofstring = TRUE;
843: else { chkarg(3,"substringn");}
844:
845: name = (char *) verify(lbot[0].val,"substringn: non symbol or string arg ");
846:
847: while (TYPE(index = lbot[1].val) != INT)
848: { lbot[1].val = errorh(Vermisc,"substringn: non integer index ",nil,
849: TRUE,0,index);
850: }
851:
852: if(!restofstring)
853: {
854: while (TYPE(length = lbot[2].val) != INT)
855: { lbot[2].val = errorh(Vermisc,"substringn: not integer length ",
856: nil, TRUE,0,length);
857: }
858: reallen = length->i;
859: }
860: else reallen = -1;
861:
862: len = strlen(name);
863: ind = index->i;
864: if(ind < 0) ind = len + 1 + ind;
865: if( ind < 1 || ind > len) return(nil);
866:
867: if(reallen == 0)
868: return((lispval)inewint(*(name + ind - 1)));
869: else {
870: char *pnt = name + ind - 1;
871: char *last = name + len -1;
872: lispval cur,start;
873:
874: protect(cur = start = newdot());
875: cur->d.car = inewint(*pnt);
876: while(++pnt <= last && --reallen != 0)
877: {
878: cur->d.cdr = newdot();
879: cur = cur->d.cdr;
880: cur->d.car = inewint(*pnt);
881: }
882: return(start);
883: }
884:
885: }
886:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.