|
|
1.1 root 1:
2: static char *sccsid = "@(#)Talloc.c 34.11 10/31/80";
3:
4: # include "global.h"
5: # include "structs.h"
6: # ifndef UNIXTS
7: # include <vadvise.h>
8: # endif
9:
10: # define NUMWORDS TTSIZE * 128 /* max number of words in P0 space */
11: # define BITQUADS TTSIZE * 2 /* length of bit map in quad words */
12:
13: # define ftstbit asm(" ashl $-2,r11,r3");\
14: asm(" bbcs r3,_bitmapq,$1");\
15: asm(" .byte 4");
16: /* define ftstbit if( readbit(p) ) return; oksetbit; */
17: # define readbit(p) ((int)bitmap[r=(int)p>>5] & (s=bitmsk[((int)p>>2)&7]))
18: # define lookbit(p) (bitmap[(int)p>>5] & bitmsk[((int)p>>2) & 7])
19: # define setbit(p) {bitmap[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
20: # define oksetbit {bitmap[r] |= s;}
21:
22: # define readchk(p) ((int)bitfre[(int)p>>5] & bitmsk[((int)p>>2)&7])
23: # define setchk(p) {bitfre[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
24: # define roundup(x,l) (((x - 1) | (l - 1)) + 1)
25:
26: /* METER denotes something added to help meter storage allocation. */
27:
28: extern struct heads header[];
29:
30: FILE * chkport; /* garbage collection dump file */
31: extern lispval datalim; /* end of data space */
32: double bitmapq[BITQUADS]; /* the bit map--one bit per long */
33: #ifdef METER
34: double Mbitmapq[BITQUADS];
35: #endif
36: double zeroq; /* a quad word of zeros */
37: char *bitmap = (char *) bitmapq; /* byte version of bit map array */
38: int *bitmapi = (int *) bitmapq; /* integer version of bit map array */
39: #ifdef METER
40: int *Mbitmapi = (int *) Mbitmapq; /* integer version of bit map array */
41: int freefree,usedfree,freeused,usedused;
42: #endif
43: #ifndef METER
44: int freefree,usedfree,freeused,usedused; /* need so external refs will be
45: satisfied, remove when get rid
46: of meter stuff
47: */
48: #endif
49: char bitmsk[8]={1,2,4,8,16,32,64,128}; /* used by bit-marking macros */
50: extern int *bind_lists ; /* lisp data for compiled code */
51:
52: char *xsbrk();
53: char *gethspace();
54:
55:
56: int atmlen;
57:
58: extern struct types atom_str, strng_str, int_str, dtpr_str, doub_str,
59: array_str, sdot_str, val_str, funct_str, hunk_str[];
60:
61: lispval hunk_items[7], hunk_pages[7], hunk_name[7];
62:
63: extern int initflag; /* starts off TRUE: initially gc not allowed */
64:
65: int gcflag = FALSE; /* TRUE during garbage collection */
66:
67: int current = 0; /* number of pages currently allocated */
68:
69: static struct types *(spaces[NUMSPACES]) =
70: {&atom_str, &strng_str, &int_str,
71: &dtpr_str, &doub_str, &array_str,
72: &sdot_str, &val_str, &funct_str,
73: &hunk_str[0], &hunk_str[1], &hunk_str[2],
74: &hunk_str[3], &hunk_str[4], &hunk_str[5],
75: &hunk_str[6]};
76:
77: /* this is a table of pointers to collectable struct types objects
78: * the index is the type number.
79: */
80: struct types *gcableptr[] =
81: { (struct types *) 0, /* strings not collectable */
82: (struct types *) 0, /* atoms not collectable */
83: &int_str, &dtpr_str, &doub_str,
84: (struct types *) 0, /* binary objects not collectable */
85: (struct types *) 0, /* port objects not collectable */
86: &array_str,
87: (struct types *) 0, /* gap in the type number sequence */
88: &sdot_str,&val_str,
89: &hunk_str[0], &hunk_str[1], &hunk_str[2],
90: &hunk_str[3], &hunk_str[4], &hunk_str[5],
91: &hunk_str[6]};
92:
93:
94: /** get_more_space(type_struct) *****************************************/
95: /* */
96: /* Allocates and structures a new page, returning 0. */
97: /* If no space is available, returns 1. */
98:
99: get_more_space(type_struct)
100: struct types *type_struct;
101: {
102: int cntr;
103: char *start;
104: int *loop, *temp;
105: lispval p, plim;
106: struct heads *next; extern char holend[];
107:
108: if(initflag == FALSE)
109: /* mustn't look at plist of plima too soon */
110: {
111: while( plim=copval(plima,(lispval)CNIL), TYPE(plim)!=INT )
112: copval(plima,error("BAD PAGE LIMIT",TRUE));
113: if( plim->i <= current ) return(1); /* Can't allocate */
114: }
115:
116: if( current >= TTSIZE ) return(2);
117:
118: #ifdef HOLE
119: if(type_struct==&strng_str || (type_struct==&funct_str))
120: start = gethspace(NBPG,type_struct->type);
121: else
122: #endif
123: start = xsbrk();
124:
125:
126: SETTYPE(start, type_struct->type); /* set type of page */
127:
128: /* bump the page counter for this space */
129:
130: ++((*(type_struct->pages))->i);
131:
132: type_struct->space_left = type_struct->space;
133: if(start >= holend) {
134: next = &header[ current++ ];
135: next->pntr = start;
136: next->link = type_struct->first;
137: type_struct->first = next;
138: }
139: if(type_struct==&strng_str) {
140: type_struct->next_free = start;
141: return(0); /* space was available */
142: }
143: type_struct->first = next;
144: temp = loop = (int *) start;
145: for(cntr=1; cntr < type_struct->space; cntr++)
146: loop = (int *) (*loop = (int) (loop + type_struct->type_len));
147: *loop = (int) (type_struct->next_free);
148: type_struct->next_free = (char *) temp;
149:
150: /* if type atom, set pnames to CNIL */
151:
152: if( type_struct == &atom_str )
153: for(cntr=0, p=(lispval) temp; cntr<atom_str.space; ++cntr)
154: {
155: p->a.pname = (char *) CNIL;
156: p = (lispval) ((int *)p + atom_str.type_len);
157: }
158: return(0); /* space was available */
159: }
160:
161:
162: /** next_one(type_struct) ************************************************/
163: /* */
164: /* Allocates one new item of each kind of space, except STRNG. */
165: /* If there is no space, calls gc, the garbage collector. */
166: /* If there is still no space, allocates a new page using */
167: /* get_more_space(type_struct) */
168:
169: lispval
170: next_one(type_struct)
171: struct types *type_struct;
172: {
173:
174: register char *temp;
175: snpand(1);
176:
177: while(type_struct->next_free == (char *) CNIL)
178: {
179: int g;
180:
181: if((type_struct->type != ATOM) && /* can't collect atoms */
182: (type_struct->type != STRNG) && /* can't collect strings */
183: (type_struct->type != BCD) && /* nor function headers */
184: (gcthresh->i <= current) && /* threshhold for gc */
185: gcdis->a.clb == nil && /* gc not disabled */
186: (NOTNIL(copval(gcload,CNIL)) || (loading->a.clb != tatom)) &&
187: /* not to collect during load */
188: (initflag == FALSE) && /* dont gc during init */
189: (gcflag == FALSE)) /* don't recurse gc */
190:
191: {
192: /* fputs("Collecting",poport);
193: dmpport(poport);*/
194: gc(type_struct); /* collect */
195: }
196:
197: if( type_struct->next_free != (char *) CNIL ) break;
198:
199: if(! (g=get_more_space(type_struct))) break;
200:
201: if( g==1 )
202: {
203: plimit->i = current+NUMSPACES;
204: /* allow a few more pages */
205: copval(plima,plimit); /* restore to reserved reg */
206:
207: error("PAGE LIMIT EXCEEDED--EMERGENCY PAGES ALLOCATED",
208: TRUE);
209: }
210: else error("SORRY, ABSOLUTE PAGE LIMIT HAS BEEN REACHED",
211: TRUE);
212: }
213:
214: temp = type_struct->next_free;
215: type_struct->next_free = * (char **)(type_struct->next_free);
216: return((lispval) temp);
217: }
218:
219: lispval
220: newint()
221: {
222: ++(int_items->i);
223: return(next_one(&int_str));
224: }
225:
226: lispval
227: newdot()
228: {
229: lispval temp;
230:
231: ++(dtpr_items->i);
232: temp = next_one(&dtpr_str);
233: temp->d.car = temp->d.cdr = nil;
234: return(temp);
235: }
236:
237: lispval
238: newdoub()
239: {
240: ++(doub_items->i);
241: return(next_one(&doub_str));
242: }
243:
244: lispval
245: newsdot()
246: {
247: register lispval temp;
248: ++(dtpr_items->i);
249: temp = next_one(&sdot_str);
250: temp->d.car = temp->d.cdr = 0;
251: return(temp);
252: }
253:
254: struct atom *
255: newatom() {
256: struct atom *save;
257:
258: ++(atom_items->i);
259: save = (struct atom *) next_one(&atom_str) ;
260: save->plist = save->fnbnd = nil;
261: save->hshlnk = (struct atom *)CNIL;
262: save->clb = CNIL;
263: save->pname = newstr();
264: return (save);
265: }
266:
267: char *newstr() {
268: char *save;
269: int atmlen2,atmlen;
270:
271: ++(str_items->i);
272: atmlen = strlen(strbuf)+1;
273: if(atmlen > strng_str.space_left)
274: while(get_more_space(&strng_str))
275: error("YOU HAVE RUN OUT OF SPACE",TRUE);
276: strcpy((save = strng_str.next_free), strbuf);
277: atmlen2 = atmlen;
278: while(atmlen2 & 3) ++atmlen2; /* even up length of string */
279: strng_str.next_free += atmlen2;
280: strng_str.space_left -= atmlen2;
281: return(save);
282: }
283:
284: char *inewstr(s) char *s;
285: {
286: strbuf[STRBLEN-1] = '\0';
287: strcpyn(strbuf,s,STRBLEN-1);
288: return(newstr());
289: }
290:
291: lispval
292: newarray()
293: {
294: register lispval temp;
295:
296: ++(array_items->i);
297: temp = next_one(&array_str);
298: temp->ar.data = (char *)nil;
299: temp->ar.accfun = nil;
300: temp->ar.aux = nil;
301: temp->ar.length = SMALL(0);
302: temp->ar.delta = SMALL(0);
303: return(temp);
304: }
305:
306: lispval
307: badcall()
308: { error("BAD FUNCTION DESCRIPTOR USED IN CALL",FALSE); }
309:
310: lispval
311: newfunct()
312: {
313: register lispval temp;
314: ++(funct_items->i);
315: temp = next_one(&funct_str);
316: temp->bcd.entry = badcall;
317: temp->bcd.discipline = nil;
318: return(temp);
319: }
320:
321: lispval
322: newval()
323: {
324: register lispval temp;
325: ++(val_items->i);
326: temp = next_one(&val_str);
327: temp->l = nil;
328: return(temp);
329: }
330:
331: lispval
332: newhunk(hunknum)
333: int hunknum;
334: {
335: register lispval temp;
336:
337: ++(hunk_items[hunknum]->i); /* Update used hunks count */
338: temp = next_one(&hunk_str[hunknum]); /* Get a hunk */
339: return(temp);
340: }
341:
342: lispval
343: inewval(arg) lispval arg;
344: {
345: lispval temp;
346: ++(val_items->i);
347: temp = next_one(&val_str);
348: temp->l = arg;
349: return(temp);
350: }
351:
352:
353: /** Ngc *****************************************************************/
354: /* */
355: /* LISP interface to gc. */
356:
357: lispval Ngc()
358: {
359: lispval temp;
360:
361: if( ISNIL(lbot->val) ) return(gc(CNIL));
362:
363: if( TYPE(lbot->val) != DTPR ) error("BAD CALL TO GC",FALSE);
364:
365: chkport = poport;
366:
367: if( NOTNIL(lbot->val->d.car) )
368: {
369: temp = eval(lbot->val->d.car);
370: if( TYPE(temp) == PORT ) chkport = temp->p;
371: }
372:
373: gc1(TRUE);
374:
375: return(nil);
376: }
377:
378: /** gc(type_struct) *****************************************************/
379: /* */
380: /* garbage collector: Collects garbage by mark and sweep algorithm. */
381: /* After this is done, calls the Nlambda, gcafter. */
382: /* gc may also be called from LISP, as a lambda of no arguments. */
383:
384: lispval
385: gc(type_struct)
386: struct types *type_struct;
387: {
388: lispval save;
389: struct {
390: long mytime;
391: long allelse[3];
392: } begin, finish;
393: extern int GCtime;
394:
395: save = copval(gcport,CNIL);
396: if(GCtime)
397: times(&begin);
398:
399: while( (TYPE(save) != PORT) && NOTNIL(save))
400: save = error("NEED PORT FOR GC",TRUE);
401:
402: chkport = (ISNIL(save) ? poport : save->p);
403:
404: gc1(NOTNIL(copval(gccheck,CNIL)) || (chkport!=poport)); /* mark&sweep */
405:
406: /* Now we call gcafter--special case if gc called from LISP */
407:
408: if( type_struct == (struct types *) CNIL )
409: gccall1->d.cdr = nil; /* make the call "(gcafter)" */
410: else
411: {
412: gccall1->d.cdr = gccall2;
413: gccall2->d.car = *(type_struct->type_name);
414: }
415: {lispval temp;temp = rdrsdot, rdrsdot = rdrsdot2, rdrsdot2 = temp; /*KLUDGE*/}
416: gcflag = TRUE; /* flag to indicate in garbage collector */
417: save = eval(gccall1); /* call gcafter */
418: gcflag = FALSE; /* turn off flag */
419: {lispval temp;temp = rdrsdot, rdrsdot = rdrsdot2, rdrsdot2 = temp; /*KLUDGE*/}
420:
421: if(GCtime) {
422: times(&finish);
423: GCtime += (finish.mytime - begin.mytime);
424: }
425: return(save); /* return result of gcafter */
426: }
427:
428:
429:
430: /* gc1() **************************************************************/
431: /* */
432: /* Mark-and-sweep phase */
433:
434: gc1(chkflag) int chkflag;
435: {
436: int j, typep,k;
437: register int *start,bvalue,type_len;
438: register struct types *s;
439: int *point,i,freecnt,itemstogo,bits,bindex,type,enddat;
440: struct heads *loop;
441: struct argent *loop2;
442: struct nament *loop3;
443: #ifdef METER
444: int Mbvalue;
445: #endif
446: int markdp();
447: int debugin = FALSE; /* temp debug flag */
448: extern int *beginsweep;
449: #define ERDB(s) { printf(s); fflush(stdout); }
450:
451: #ifndef UNIXTS
452: vadvise(VA_ANOM);
453: /* decide whether to check LISP structure or not */
454: #endif
455:
456:
457:
458: /* first set all bit maps to zero */
459:
460:
461: if(debugin) ERDB("Begin gc\n");
462: enddat = (int)datalim >> 8;
463: for(bvalue=0; bvalue < (int)enddat ; ++bvalue)
464: {
465: #ifdef METER
466: /* Mbitmapq[bvalue] = bitmapq[bvalue]; /* remember old vals */
467: /* the C compiler will use a movd if we let it,and this
468: will not work since the bit maps may be illegal
469: floating point values
470: */
471: asm(" movq _bitmapq[r10],_Mbitmapq[r10] ");
472: #endif
473: bitmapq[bvalue] = zeroq;
474: }
475:
476: /* try the movc5 to clear the bit maps */
477: /* blzero(bitmap,TTSIZE * 16); */
478:
479:
480: /* then mark all atoms' plists, clbs, and function bindings */
481:
482: for(loop=atom_str.first; loop!=(struct heads *)CNIL; loop=loop->link)
483: for(start=(int *)(loop->pntr), i=1;
484: i <= atom_str.space;
485: start = start + atom_str.type_len, ++i)
486: {
487:
488: /* unused atoms are marked with pname == CNIL */
489: /* this is done by get_more_space, as well as */
490: /* by gc (in the future) */
491:
492: if(((lispval)start)->a.pname == (char *)CNIL) continue;
493: #define MARKSUB(p) if(nil!=((lispval)start)->p)markdp(((lispval)start)->p);
494: MARKSUB(a.clb);
495: MARKSUB(a.fnbnd);
496: MARKSUB(a.plist);
497: }
498:
499: /* Mark all the atoms and ints associated with the hunk
500: data types */
501:
502: for(i=0; i<8; i++) {
503: markdp(hunk_items[i]);
504: markdp(hunk_name[i]);
505: markdp(hunk_pages[i]);
506: }
507: /* next run up the name stack */
508: if(debugin) ERDB("name stack\n");
509: for(loop2 = np - 1; loop2 >= orgnp; --loop2) markdp((loop2->val));
510:
511: /* now the bindstack (vals only, atoms are marked elsewhere ) */
512: for(loop3 = bnp - 1; loop3 >= orgbnp; --loop3)markdp(loop3->val);
513:
514: if(debugin) ERDB("compiler stuff\n");
515: /* from TBL 29july79 */
516: /* next mark all compiler linked data */
517: point = bind_lists;
518: while((start = point) != (int *)CNIL) {
519: if(debugin) ERDB("once ");
520: while( *start != -1 )
521: markdp(*start++);
522: point = (int *)*(point-1);
523: }
524: /* end from TBL */
525:
526: if(debugin) ERDB("signif stuff\n");
527: /* next mark all system-significant lisp data */
528:
529: for(i=0; i<SIGNIF; ++i) markdp((lispsys[i]));
530:
531: if(debugin) printf("time to sweep up\n");
532: /* all accessible data has now been marked. */
533: /* all collectable spaces must be swept, */
534: /* and freelists constructed. */
535:
536: /* first clear the structure elements for types
537: * we will sweep
538: */
539:
540: for(k=0 ; k <= HUNK128 ; k++)
541: {
542: if( s=gcableptr[k] )
543: {
544: (*(s->items))->i = 0;
545: s->space_left = 0;
546: s->next_free = (char *) CNIL;
547: }
548: }
549:
550:
551: /* sweep up in memory looking at gcable pages */
552:
553: for(start = beginsweep, bindex = (int)start >> 7;
554: start < (int *)datalim;
555: start += 128)
556: {
557: /* printf(" start %x, bindex %x\n",start,bindex); */
558: if(!(s=gcableptr[type = TYPE(start)]))
559: {
560: bindex += 4; /* and 4 words of 32 bit bitmap words */
561: continue;
562: }
563:
564: freecnt = 0; /* number of free items found */
565: itemstogo = s->space; /* number of items per page */
566: bits = 32; /* number of bits per word */
567: type_len = s->type_len;
568:
569: /* printf(" s %d, itemstogo %d, len %d\n",s,itemstogo,type_len);*/
570: bvalue = bitmapi[bindex++];
571: #ifdef METER
572: Mbvalue = Mbitmapi[bindex-1];
573: #endif
574:
575: point = start;
576: while(TRUE)
577: {
578: /*printf(" bv: %08x, ",bvalue);*/
579: if(!(bvalue & 1)) /* if data element is not marked */
580: {
581: freecnt++;
582: *point = (int) (s->next_free) ;
583: s->next_free = (char *) point;
584: #ifdef METER
585: if(type == DTPR)
586: {
587: if(Mbvalue & 1) usedfree++;
588: else freefree++;
589: }
590: #endif
591: }
592: #ifdef METER
593: else if(type == DTPR)
594: {
595: if (Mbvalue & 1) usedused++;
596: else freeused++;
597: }
598: #endif
599:
600: if( --itemstogo <= 0 )
601: { if(type_len >= 64)
602: {
603: bindex++;
604: if(type_len >=128) bindex += 2;
605: }
606: break;
607: }
608:
609: point += type_len;
610: /* shift over mask by number of words in data type */
611:
612: if( (bits -= type_len) > 0)
613: { bvalue = bvalue >> type_len;
614: #ifdef METER
615: Mbvalue = Mbvalue >> type_len;
616: #endif
617: }
618: else if( bits == 0 )
619: { bvalue = bitmapi[bindex++];
620: #ifdef METER
621: Mbvalue = Mbitmapi[bindex-1];
622: #endif
623: bits = 32;
624: }
625: else
626: { bits = -bits;
627: while( bits >= 32) { bindex++;
628: bits -= 32;
629: }
630: bvalue = bitmapi[bindex++];
631: bvalue = bvalue >> bits;
632: #ifdef METER
633: Mbvalue = Mbitmapi[bindex-1];
634: Mbvalue = Mbvalue >> bits;
635: #endif
636: bits = 32 - bits;;
637: }
638: }
639:
640: /* printf(" t %d,fr %d ",type,freecnt); */
641: s->space_left += freecnt;
642: (*(s->items))->i += s->space - freecnt;
643: }
644:
645: #ifndef UNIXTS
646: vadvise(VA_NORM);
647: #endif
648: }
649:
650: /** alloc() *************************************************************/
651: /* */
652: /* This routine tries to allocate one more page of the space named */
653: /* by the argument. If no more space is available returns 1, else 0. */
654:
655: lispval
656: alloc(tname,npages)
657: lispval tname; int npages;
658: {
659: int ii, jj;
660:
661: ii = typenum(tname);
662:
663: if(((int)datalim >> 9) + npages > TTSIZE)
664: error("Space request would exceed maximum memory allocation",FALSE);
665:
666: for( jj=0; jj<npages; ++jj)
667: if(get_more_space(spaces[ii])) break;
668: return(inewint(jj));
669: }
670:
671: lispval
672: csegment(tname,nitems,useholeflag)
673: lispval tname; int nitems;
674: {
675: int ii, jj;
676: char *charadd;
677:
678: ii = typenum(tname);
679:
680: nitems = nitems*4*spaces[ii]->type_len; /* find c-length of space */
681: nitems = roundup(nitems,512); /* round up to right length */
682: #ifdef HOLE
683: if((tname==str_name) && useholeflag)
684: charadd = gethspace(nitems,ii);
685: else
686: #endif
687: {
688: current += nitems/512;
689: charadd = sbrk(nitems);
690: datalim = (lispval)(charadd+nitems);
691: }
692: if( (int) charadd == 0 )
693: error("NOT ENOUGH SPACE FOR ARRAY",FALSE);
694: if((((int)datalim) >> 9) > TTSIZE) {
695: datalim = (lispval) (TTSIZE << 9);
696: badmem(53);
697: }
698: for(jj=0; jj<nitems; jj=jj+512) {
699: SETTYPE(charadd+jj, spaces[ii]->type);
700: }
701: blzero(charadd,nitems);
702: return((lispval)charadd);
703: }
704:
705: int csizeof(tname) lispval tname;
706: {
707: return( spaces[typenum(tname)]->type_len * 4 );
708: }
709:
710: int typenum(tname) lispval tname;
711: {
712: int ii;
713:
714: chek: for(ii=0; ii<NUMSPACES; ++ii)
715: if(tname == *(spaces[ii]->type_name)) break;
716: if(ii == NUMSPACES)
717: {
718: tname = error("BAD TYPE NAME",TRUE);
719: goto chek;
720: }
721:
722: return(ii);
723:
724: }
725: char *
726: gethspace(segsiz,type)
727: {
728: extern usehole; extern char holend[]; extern char *curhbeg;
729: register char *value;
730:
731: if(usehole) {
732: curhbeg = (char *) roundup(((int)curhbeg),NBPG);
733: if((holend - curhbeg) < segsiz)
734: { printf("[fasl hole filled up]\n");
735: usehole = FALSE;
736: } else {
737: value = curhbeg;
738: curhbeg = curhbeg + segsiz;
739: /*printf("start %d, finish %d, size %d\n",value, curhbeg,segsiz);*/
740: return(value);
741: }
742: }
743: value = (ysbrk(segsiz/NBPG,type));
744: datalim = (lispval)(value + segsiz);
745: return(value);
746: }
747: gcrebear()
748: {
749: #ifdef HOLE
750: /* this gets done upon rebirth */
751: strng_str.space_left = 0;
752: funct_str.space_left = 0;
753: funct_str.next_free = (char *) CNIL;
754: #endif
755: }
756:
757: /** markit(p) ***********************************************************/
758: /* just calls markdp */
759:
760: markit(p) lispval *p; { markdp(*p); }
761:
762: /** markdp(p) ***********************************************************/
763: /* */
764: /* markdp is the routine which marks each data item. If it is a */
765: /* dotted pair, the car and cdr are marked also. */
766: /* An iterative method is used to mark list structure, to avoid */
767: /* excessive recursion. */
768:
769:
770: markdp(p) register lispval p;
771: {
772: /* register int r, s; (goes with non-asm readbit, oksetbit) */
773: /* register hsize, hcntr; */
774: int hsize, hcntr;
775:
776: ptr_loop:
777: if((int)p <= 0) return; /* do not mark special data types or nil=0 */
778:
779: switch( TYPE(p) )
780: {
781: case INT:
782: case DOUB:
783: /* setbit(p);*/
784: ftstbit;
785: return;
786: case VALUE:
787: ftstbit;
788: p = p->l;
789: goto ptr_loop;
790: case DTPR:
791: ftstbit;
792: markdp(p->d.car);
793: p = p->d.cdr;
794: goto ptr_loop;
795:
796: case ARRAY:
797: ftstbit; /* mark array itself */
798:
799: markdp(p->ar.accfun); /* mark access function */
800: markdp(p->ar.aux); /* mark aux data */
801: markdp(p->ar.length); /* mark length */
802: markdp(p->ar.delta); /* mark delta */
803: if(TYPE(p->ar.aux)==DTPR && p->ar.aux->d.car==Vnogbar)
804: return;
805: {
806: /* register int i, l; int d; */
807: /* register char *dataptr = p->ar.data; */
808: int i,l,d;
809: char *dataptr = p->ar.data;
810:
811: for(i=0, l=p->ar.length->i, d=p->ar.delta->i; i<l; ++i)
812: {
813: markdp(dataptr);
814: dataptr += d;
815: }
816: return;
817: }
818: case SDOT:
819: do {
820: ftstbit;
821: p = p->s.CDR;
822: } while (p!=0);
823: return;
824:
825: case BCD:
826: ftstbit;
827: markdp(p->bcd.discipline);
828: return;
829:
830: case HUNK2:
831: case HUNK4:
832: case HUNK8:
833: case HUNK16:
834: case HUNK32:
835: case HUNK64:
836: case HUNK128:
837: {
838: hsize = 2 << HUNKSIZE(p);
839: ftstbit;
840: for (hcntr = 0; hcntr < hsize; hcntr++)
841: markdp(p->h.hunk[hcntr]);
842: return;
843: }
844: }
845: return;
846: }
847:
848:
849:
850: char *
851: xsbrk()
852: {
853: static char *xx; /* pointer to next available blank page */
854: extern int xcycle; /* number of blank pages available */
855: lispval u; /* used to compute limits of bit table */
856:
857: if( (xcycle--) <= 0 )
858: {
859: xcycle = 15;
860: xx = sbrk(16*NBPG); /* get pages 16 at a time */
861: if( (int)xx== -1 )
862: lispend("For sbrk from lisp: no space... Goodbye!");
863: goto done;
864: }
865: xx += NBPG;
866: done: if( (u = (lispval)(xx+NBPG)) > datalim ) datalim = u;
867: return(xx);
868: }
869:
870: char *ysbrk(pages,type) int pages, type;
871: {
872: char *xx; /* will point to block of storage */
873: int i;
874:
875: xx = sbrk(pages*NBPG);
876: if((int)xx == -1)
877: error("OUT OF SPACE FOR ARRAY REQUEST",FALSE);
878:
879: datalim = (lispval)(xx+pages*NBPG); /* compute bit table limit */
880:
881: /* set type for pages */
882:
883: for(i = 0; i < pages; ++i) {
884: SETTYPE((xx + i*NBPG),type);
885: }
886:
887: return(xx); /* return pointer to block of storage */
888: }
889:
890: #ifdef VMS
891: /* sbrk -
892: * this function is used by the VMS franz to allocate space.
893: * It allocates space in the zfreespace array.
894: * The single argument passed to sbrk is the number of bytes to allocate
895: *
896: */
897:
898: extern char zfreespace[];
899: extern char *lsbrkpnt;
900:
901: char *
902: sbrk(n)
903: {
904: char *result;
905: if(lsbrkpnt == (char *)0)
906: {
907: lsbrkpnt = (char *) roundup((int)zfreespace,NBPG);
908: }
909: result = lsbrkpnt;
910: /* printf("lispbrk: %x \n",lsbrkpnt);
911: fflush(stdout); */
912: lsbrkpnt += n;
913: if(lsbrkpnt > &zfreespace[FREESIZE])
914: error("sbrk: out of space ",FALSE);
915: return(result);
916: }
917: #endif
918: /* getatom **************************************************************/
919: /* returns either an existing atom with the name specified in strbuf, or*/
920: /* if the atom does not already exist, regurgitates a new one and */
921: /* returns it. */
922: lispval
923: getatom()
924: { register lispval aptr;
925: register char *name, *endname;
926: register int hash;
927: register struct argent *lbot, *np;
928: lispval b;
929: char c;
930:
931: name = strbuf;
932: if (*name == (char)0377) return (eofa);
933: hash = hashfcn(name);
934: atmlen = strlen(name) + 1;
935: aptr = (lispval) hasht[hash];
936: while (aptr != CNIL)
937: if (strcmp(name,aptr->a.pname)==0)
938: return (aptr);
939: else
940: aptr = (lispval) aptr->a.hshlnk;
941: aptr = (lispval) newatom();
942: aptr->a.hshlnk = hasht[hash];
943: hasht[hash] = (struct atom *) aptr;
944: endname = name + atmlen - 2;
945: if ((atmlen != 4) && (*name == 'c') && (*endname == 'r'))
946: {
947: b = newdot();
948: protect(b);
949: b->d.car = lambda;
950: b->d.cdr = newdot();
951: b = b->d.cdr;
952: b->d.car = newdot();
953: (b->d.car)->d.car = xatom;
954: while(TRUE)
955: {
956: b->d.cdr = newdot();
957: b= b->d.cdr;
958: if(++name == endname)
959: {
960: b->d.car= (lispval) xatom;
961: aptr->a.fnbnd = unprot();
962: break;
963: }
964: b->d.car= newdot();
965: b= b->d.car;
966: if((c = *name) == 'a') b->d.car = cara;
967: else if (c == 'd') b->d.car = cdra;
968: else{ unprot();
969: break;
970: }
971: }
972: }
973:
974: return(aptr);
975: }
976:
977: /* our hash function */
978:
979: hashfcn(symb)
980: char *symb;
981: {
982: register int i;
983: for (i=0 ; *symb ; i += i + *symb++);
984: return(i & (HASHTOP-1));
985: }
986:
987: extern struct atom *hasht[HASHTOP];
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.