Annotation of 43BSDTahoe/ucb/lisp/franz/alloc.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char *rcsid =
        !             3:    "$Header: alloc.c,v 1.13 87/12/11 17:27:45 sklower Exp $";
        !             4: #endif
        !             5: 
        !             6: /*
        !             7:  *     alloc.c                         $Locker:  $
        !             8:  * storage allocator and garbage collector
        !             9:  *
        !            10:  * (c) copyright 1982, Regents of the University of California
        !            11:  */
        !            12:  
        !            13: # include "global.h"
        !            14: # include "structs.h"
        !            15: 
        !            16: #include <sys/types.h>
        !            17: #include <sys/times.h>
        !            18: #ifdef METER
        !            19: #include <sys/vtimes.h>
        !            20: #endif
        !            21:  
        !            22: # define NUMWORDS TTSIZE * 128  /*  max number of words in P0 space  */
        !            23: # define BITQUADS TTSIZE * 2   /*  length of bit map in quad words  */
        !            24: # define BITLONGS TTSIZE * 4   /*  length of bit map in long words  */
        !            25: 
        !            26: # ifdef vax
        !            27: # define ftstbit       asm("   ashl    $-2,r11,r3");\
        !            28:                        asm("   bbcs    r3,_bitmapi,1f");\
        !            29:                        asm("   ret"); \
        !            30:                        asm("1:");
        !            31: 
        !            32: /* setbit is a fast way of setting a bit, it is like ftstbit except it
        !            33:  * always continues on to the next instruction
        !            34:  */
        !            35: # define setbit                asm("   ashl    $-2,r11,r0"); \
        !            36:                        asm("   bbcs    r0,_bitmapi,$0");
        !            37: # endif
        !            38: 
        !            39: # if m_68k
        !            40: # define ftstbit       {if(Itstbt()) return;}
        !            41: # define setbit                Itstbt()
        !            42: # endif
        !            43: 
        !            44: # ifdef tahoe
        !            45: # define ftstbit       if( readbit(p) ) return; oksetbit;
        !            46: # define setbit                {bitmapi[(int)p>>7] |= bitmsk[((int)p >> 2)&31];}
        !            47: # define readbit(p)    ((int)bitmapi[r=(int)p>>7] & (s=bitmsk[((int)p>>2)&31]))
        !            48: # define oksetbit      {bitmapi[r] |= s;}
        !            49: # endif
        !            50: 
        !            51: /*     Unused bit macros
        !            52: # define lookbit(p)    (bbitmap[(int)p>>5] & bitmsk[((int)p>>2) & 7])
        !            53: # define readchk(p)    ((int)bitfre[(int)p>>5] & bitmsk[((int)p>>2)&7])
        !            54: # define setchk(p)     {bitfre[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
        !            55: */
        !            56: 
        !            57: # define roundup(x,l)  (((x - 1) | (l - 1)) + 1) 
        !            58: 
        !            59: # define MARKVAL(v)    if(((int)v) >= (int)beginsweep) markdp(v);
        !            60: # define ATOLX(p)      ((((int)p)-OFFSET)>>7)
        !            61: 
        !            62: /* the Vax hardware only allows 2^16-1 bytes to be accessed with one
        !            63:  * movc5 instruction.  We use the movc5 instruction to clear the 
        !            64:  * bitmaps.
        !            65:  */
        !            66: # define MAXCLEAR ((1<<16)-1)
        !            67: 
        !            68: /* METER denotes something added to help meter storage allocation. */
        !            69: 
        !            70: extern int *beginsweep;                        /* first sweepable data         */
        !            71: extern char purepage[];
        !            72: extern int fakettsize;
        !            73: extern int gcstrings;
        !            74: int debugin  = FALSE;                  /* temp debug flag */
        !            75: 
        !            76: extern lispval datalim;                        /*  end of data space */
        !            77: int bitmapi[BITLONGS];                 /*  the bit map--one bit per long  */
        !            78: double zeroq;                          /*  a quad word of zeros  */
        !            79: char *bbitmap = (char *) bitmapi;      /*  byte version of bit map array */
        !            80: double  *qbitmap = (double *) bitmapi; /*  integer version of bit map array */
        !            81: #ifdef METER
        !            82: extern int gcstat;
        !            83: extern struct vtimes
        !            84:        premark,presweep,alldone;       /* actually struct tbuffer's */
        !            85: 
        !            86: extern int mrkdpcnt;
        !            87: extern int conssame, consdiff,consnil; /* count of cells whose cdr point
        !            88:                                         * to the same page and different
        !            89:                                         * pages respectively
        !            90:                                         */
        !            91: #endif
        !            92: int bitmsk[32]={1,2,4,8,16,32,64,128,  /*  used by bit-marking macros  */
        !            93:                0x100, 0x200, 0x400, 0x800, 
        !            94:                0x1000, 0x2000, 0x4000, 0x8000, 
        !            95:                0x10000, 0x20000, 0x40000, 0x80000, 
        !            96:                0x100000, 0x200000, 0x400000, 0x800000, 
        !            97:                0x1000000, 0x2000000, 0x4000000, 0x8000000, 
        !            98:                0x10000000, 0x20000000, 0x40000000, 0x80000000}; 
        !            99: extern int  *bind_lists;               /*  lisp data for compiled code */
        !           100: 
        !           101: char *xsbrk();
        !           102: char *gethspace();
        !           103: 
        !           104: 
        !           105: extern struct types atom_str, strng_str, int_str, dtpr_str, doub_str,
        !           106:        array_str, sdot_str, val_str, funct_str, hunk_str[], vect_str,
        !           107:        vecti_str, other_str;
        !           108: 
        !           109: extern struct str_x str_current[];
        !           110: 
        !           111: lispval hunk_items[7], hunk_pages[7], hunk_name[7];
        !           112: 
        !           113: extern int initflag; /* starts off TRUE: initially gc not allowed */
        !           114: 
        !           115: 
        !           116: /* this is a table of pointers to all struct types objects
        !           117:  * the index is the type number.
        !           118:  */
        !           119: static struct types *spaces[NUMSPACES] = 
        !           120:        {&strng_str, &atom_str, &int_str,
        !           121:         &dtpr_str, &doub_str, &funct_str, 
        !           122:         (struct types *) 0,  /* port objects not allocated in this way  */
        !           123:         &array_str,
        !           124:         &other_str,  /* other objects not allocated in this way  */
        !           125:         &sdot_str,&val_str, 
        !           126:         &hunk_str[0], &hunk_str[1], &hunk_str[2],
        !           127:         &hunk_str[3], &hunk_str[4], &hunk_str[5],
        !           128:         &hunk_str[6],
        !           129:         &vect_str, &vecti_str};
        !           130: 
        !           131: 
        !           132: /* this is a table of pointers to collectable struct types objects
        !           133:  * the index is the type number.
        !           134:  */
        !           135: struct types *gcableptr[] = {
        !           136: #ifndef GCSTRINGS
        !           137:      (struct types *) 0,  /* strings not collectable */
        !           138: #else
        !           139:      &strng_str,
        !           140: #endif
        !           141:      &atom_str,
        !           142:      &int_str, &dtpr_str, &doub_str,
        !           143:      (struct types *) 0,  /* binary objects not collectable */
        !           144:      (struct types *) 0,  /* port objects not collectable */
        !           145:      &array_str,
        !           146:      (struct types *) 0,  /* gap in the type number sequence */
        !           147:      &sdot_str,&val_str, 
        !           148:      &hunk_str[0], &hunk_str[1], &hunk_str[2],
        !           149:      &hunk_str[3], &hunk_str[4], &hunk_str[5],
        !           150:      &hunk_str[6],
        !           151:      &vect_str, &vecti_str};
        !           152: 
        !           153: 
        !           154: /*
        !           155:  *   get_more_space(type_struct,purep) 
        !           156:  *                                                                     
        !           157:  *  Allocates and structures a new page, returning 0.
        !           158:  *  If no space is available, returns positive number.
        !           159:  *  If purep is TRUE, then pure space is allocated.
        !           160:  */
        !           161: get_more_space(type_struct,purep)                                 
        !           162: struct types *type_struct;
        !           163: {
        !           164:        int cntr;
        !           165:        char *start;
        !           166:        int *loop, *temp;
        !           167:        lispval p;
        !           168:        extern char holend[];
        !           169: 
        !           170:        if( (int) datalim >= TTSIZE*LBPG+OFFSET ) return(2);
        !           171: 
        !           172:        /*
        !           173:         * If the hole is defined, then we allocate binary objects
        !           174:         * and strings in the hole.  However we don't put strings in
        !           175:         * the hole if strings are gc'ed.
        !           176:         */
        !           177: #ifdef HOLE
        !           178:        if(   purep
        !           179: #ifndef GCSTRINGS
        !           180:           || type_struct==&strng_str
        !           181: #endif
        !           182:           || type_struct==&funct_str)
        !           183:                start = gethspace(LBPG,type_struct->type);
        !           184:        else
        !           185: #endif
        !           186:                start = xsbrk(1);               /* get new page */
        !           187: 
        !           188: 
        !           189:        SETTYPE(start, type_struct->type,20);  /*  set type of page  */
        !           190: 
        !           191:        purepage[ATOX(start)] = (char)purep;  /* remember if page was pure*/
        !           192: 
        !           193:        /* bump the page counter for this space if not pure */
        !           194: 
        !           195:        if(!purep) ++((*(type_struct->pages))->i);
        !           196: 
        !           197:        type_struct->space_left = type_struct->space;
        !           198:        temp = loop = (int *) start;
        !           199:        for(cntr=1; cntr < type_struct->space; cntr++)
        !           200:                loop = (int *) (*loop = (int) (loop + type_struct->type_len));
        !           201: 
        !           202:        /* attach new cells to either the pure space free list  or the 
        !           203:         * standard free list
        !           204:         */
        !           205:        if(purep) {
        !           206:            *loop = (int) (type_struct->next_pure_free);
        !           207:            type_struct->next_pure_free = (char *) temp;
        !           208:        }
        !           209:        else  {
        !           210:            *loop = (int) (type_struct->next_free);
        !           211:            type_struct->next_free = (char *) temp;
        !           212:        }
        !           213: 
        !           214:        /*  if type atom, set pnames to CNIL  */
        !           215: 
        !           216:        if( type_struct == &atom_str )
        !           217:                for(cntr=0, p=(lispval) temp; cntr<atom_str.space; ++cntr)
        !           218:                        {
        !           219:                        p->a.pname = (char *) CNIL;
        !           220:                        p = (lispval) ((int *)p + atom_str.type_len);
        !           221:                        }
        !           222:        return(0);  /*  space was available  */
        !           223: }
        !           224: 
        !           225: 
        !           226: /*
        !           227:  * next_one(type_struct) 
        !           228:  *
        !           229:  *  Allocates one new item of each kind of space, except STRNG.        
        !           230:  *  If there is no space, calls gc, the garbage collector.
        !           231:  *  If there is still no space, allocates a new page using
        !           232:  *  get_more_space
        !           233:  */
        !           234: 
        !           235: lispval
        !           236: next_one(type_struct)
        !           237: struct types *type_struct;
        !           238: {
        !           239: 
        !           240:        register char *temp;
        !           241: 
        !           242:        while(type_struct->next_free == (char *) CNIL)
        !           243:                {
        !           244:                int g;
        !           245: 
        !           246:                if(
        !           247:                   (initflag == FALSE) &&       /* dont gc during init */
        !           248: #ifndef GCSTRINGS
        !           249:                   (type_struct->type != STRNG) && /* can't collect strings */
        !           250: #else
        !           251:                   gcstrings &&                 /* user (sstatus gcstrings) */
        !           252: #endif
        !           253:                   (type_struct->type != BCD) &&   /* nor function headers  */
        !           254:                   gcdis->a.clb == nil )                /* gc not disabled */
        !           255:                                        /* not to collect during load */
        !           256: 
        !           257:                        {
        !           258:                        gc(type_struct);  /*  collect  */
        !           259:                        }
        !           260: 
        !           261:                if( type_struct->next_free != (char *) CNIL ) break;
        !           262: 
        !           263:                if(! (g=get_more_space(type_struct,FALSE))) break;
        !           264: 
        !           265:                space_warn(g);
        !           266:                }
        !           267:        temp = type_struct->next_free;
        !           268:        type_struct->next_free = * (char **)(type_struct->next_free);
        !           269:        (*(type_struct->items))->i ++;
        !           270:        return((lispval) temp);
        !           271: }
        !           272: /*
        !           273:  * Warn about exhaustion of space,
        !           274:  * shared with next_pure_free().
        !           275:  */
        !           276: space_warn(g)
        !           277: {
        !           278:        if( g==1 ) {
        !           279:            plimit->i += NUMSPACES; /*  allow a few more pages  */
        !           280:            copval(plima,plimit);       /*  restore to reserved reg  */
        !           281: 
        !           282:            error("PAGE LIMIT EXCEEDED--EMERGENCY PAGES ALLOCATED", TRUE);
        !           283:        } else error("SORRY, ABSOLUTE PAGE LIMIT HAS BEEN REACHED", TRUE);
        !           284: }
        !           285: 
        !           286: 
        !           287: /* allocate an element of a pure structure.  Pure structures will
        !           288:  * be ignored by the garbage collector.
        !           289:  */
        !           290: lispval
        !           291: next_pure_one(type_struct)
        !           292: struct types *type_struct;
        !           293: {
        !           294: 
        !           295:        register char *temp;
        !           296: 
        !           297:        while(type_struct->next_pure_free == (char *) CNIL)
        !           298:                {
        !           299:                int g;
        !           300:                if(! (g=get_more_space(type_struct,TRUE))) break;
        !           301:                space_warn(g);
        !           302:                }
        !           303: 
        !           304:        temp = type_struct->next_pure_free;
        !           305:        type_struct->next_pure_free = * (char **)(type_struct->next_pure_free);
        !           306:        return((lispval) temp);
        !           307: }
        !           308: 
        !           309: lispval
        !           310: newint()
        !           311: {
        !           312:        return(next_one(&int_str));
        !           313: }
        !           314: 
        !           315: lispval
        !           316: pnewint()
        !           317: {
        !           318:        return(next_pure_one(&int_str));
        !           319: }
        !           320: 
        !           321: lispval
        !           322: newdot()
        !           323: {
        !           324:        lispval temp;
        !           325: 
        !           326:        temp = next_one(&dtpr_str);
        !           327:        temp->d.car = temp->d.cdr = nil;
        !           328:        return(temp);
        !           329: }
        !           330: 
        !           331: lispval
        !           332: pnewdot()
        !           333: {
        !           334:        lispval temp;
        !           335: 
        !           336:        temp = next_pure_one(&dtpr_str);
        !           337:        temp->d.car = temp->d.cdr = nil;
        !           338:        return(temp);
        !           339: }
        !           340: 
        !           341: lispval
        !           342: newdoub()
        !           343: {
        !           344:        return(next_one(&doub_str));
        !           345: }
        !           346: 
        !           347: lispval
        !           348: pnewdb()
        !           349: {
        !           350:        return(next_pure_one(&doub_str));
        !           351: }
        !           352: 
        !           353: lispval
        !           354: newsdot()
        !           355: {
        !           356:        register lispval temp;
        !           357:        temp = next_one(&sdot_str);
        !           358:        temp->d.car = temp->d.cdr = 0;
        !           359:        return(temp);
        !           360: }
        !           361: 
        !           362: lispval
        !           363: pnewsdot()
        !           364: {
        !           365:        register lispval temp;
        !           366:        temp = next_pure_one(&sdot_str);
        !           367:        temp->d.car = temp->d.cdr = 0;
        !           368:        return(temp);
        !           369: }
        !           370: 
        !           371: struct atom *
        !           372: newatom(pure) {
        !           373:        struct atom *save; char *mypname;
        !           374: 
        !           375:        mypname = newstr(pure);
        !           376:        pnameprot = ((lispval) mypname);
        !           377:        save = (struct atom *) next_one(&atom_str) ;    
        !           378:        save->plist = save->fnbnd = nil;
        !           379:        save->hshlnk = (struct atom *)CNIL;
        !           380:        save->clb = CNIL;
        !           381:        save->pname = mypname;
        !           382:        return (save);
        !           383: }
        !           384: 
        !           385: char *
        !           386: newstr(purep) {
        !           387:        char *save, *strcpy();
        !           388:        int atmlen;
        !           389:        register struct str_x *p = str_current + purep;
        !           390: 
        !           391:        atmlen = strlen(strbuf)+1;
        !           392:        if(atmlen > p->space_left) {
        !           393:                if(atmlen >= STRBLEN) {
        !           394:                        save = (char *)csegment(OTHER, atmlen, purep);
        !           395:                        SETTYPE(save,STRNG,40);
        !           396:                        purepage[ATOX(save)] = (char)purep;
        !           397:                        strcpy(save,strbuf);
        !           398:                        return(save);
        !           399:                }
        !           400:                p->next_free =  (char *) (purep ?
        !           401:                        next_pure_one(&strng_str) : next_one(&strng_str)) ;
        !           402:                p->space_left = LBPG;
        !           403:        }
        !           404:        strcpy((save = p->next_free), strbuf);
        !           405:        /*while(atmlen & 3) ++atmlen;   /*  even up length of string  */
        !           406:        p->next_free += atmlen;
        !           407:        p->space_left -= atmlen;
        !           408:        return(save);
        !           409: }
        !           410: 
        !           411: static char * Iinewstr(s,purep) char *s;
        !           412: {
        !           413:        int len = strlen(s);
        !           414:        while(len > (endstrb - strbuf - 1)) atomtoolong(strbuf);
        !           415:        strcpy(strbuf,s);
        !           416:        return(newstr(purep));
        !           417: }
        !           418: 
        !           419: 
        !           420: char *inewstr(s) char *s;
        !           421: {
        !           422:        Iinewstr(s,0);
        !           423: }
        !           424: 
        !           425: char *pinewstr(s) char *s;
        !           426: {
        !           427:        Iinewstr(s,1);
        !           428: }
        !           429: 
        !           430: lispval
        !           431: newarray()
        !           432:        {
        !           433:        register lispval temp;
        !           434: 
        !           435:        temp = next_one(&array_str);
        !           436:        temp->ar.data = (char *)nil;
        !           437:        temp->ar.accfun = nil;
        !           438:        temp->ar.aux = nil;
        !           439:        temp->ar.length = SMALL(0);
        !           440:        temp->ar.delta = SMALL(0);
        !           441:        return(temp);
        !           442:        }
        !           443: 
        !           444: lispval
        !           445: newfunct()
        !           446:        {
        !           447:        register lispval temp;
        !           448:        lispval Badcall();
        !           449:        temp = next_one(&funct_str);
        !           450:        temp->bcd.start = Badcall;
        !           451:        temp->bcd.discipline = nil;
        !           452:        return(temp);
        !           453:        }
        !           454: 
        !           455: lispval
        !           456: newval()
        !           457:        {
        !           458:        register lispval temp;
        !           459:        temp = next_one(&val_str);
        !           460:        temp->l = nil;
        !           461:        return(temp);
        !           462:        }
        !           463: 
        !           464: lispval
        !           465: pnewval()
        !           466:        {
        !           467:        register lispval temp;
        !           468:        temp = next_pure_one(&val_str);
        !           469:        temp->l = nil;
        !           470:        return(temp);
        !           471:        }
        !           472: 
        !           473: lispval
        !           474: newhunk(hunknum)
        !           475: int hunknum;
        !           476:        {
        !           477:        register lispval temp;
        !           478: 
        !           479:        temp = next_one(&hunk_str[hunknum]);    /* Get a hunk */
        !           480:        return(temp);
        !           481:        }
        !           482: 
        !           483: lispval
        !           484: pnewhunk(hunknum)
        !           485: int hunknum;
        !           486:        {
        !           487:        register lispval temp;
        !           488: 
        !           489:        temp = next_pure_one(&hunk_str[hunknum]);       /* Get a hunk */
        !           490:        return(temp);
        !           491:        }
        !           492: 
        !           493: lispval
        !           494: inewval(arg) lispval arg;
        !           495:        {
        !           496:        lispval temp;
        !           497:        temp = next_one(&val_str);
        !           498:        temp->l = arg;
        !           499:        return(temp);
        !           500:        }
        !           501: 
        !           502: /*
        !           503:  * Vector allocators.
        !           504:  * a vector looks like:
        !           505:  *  longword: N = size in bytes
        !           506:  *  longword: pointer to lisp object, this is the vector property field
        !           507:  *  N consecutive bytes
        !           508:  *
        !           509:  */
        !           510: lispval getvec();
        !           511: 
        !           512: lispval
        !           513: newvec(size)
        !           514: {
        !           515:     return(getvec(size,&vect_str,FALSE));
        !           516: }
        !           517: 
        !           518: lispval
        !           519: pnewvec(size)
        !           520: {
        !           521:     return(getvec(size,&vect_str,TRUE));
        !           522: }
        !           523: 
        !           524: lispval
        !           525: nveci(size)
        !           526: {
        !           527:     return(getvec(size,&vecti_str,FALSE));
        !           528: }
        !           529: 
        !           530: lispval
        !           531: pnveci(size)
        !           532: {
        !           533:     return(getvec(size,&vecti_str,TRUE));
        !           534: }
        !           535: 
        !           536: /*
        !           537:  * getvec
        !           538:  *  get a vector of size byte, from type structure typestr and
        !           539:  * get it from pure space if purep is TRUE.
        !           540:  *  vectors are stored linked through their property field.  Thus
        !           541:  * when the code here refers to v.vector[0], it is the prop field
        !           542:  * and vl.vectorl[-1] is the size field.   In other code,
        !           543:  * v.vector[-1] is the prop field, and vl.vectorl[-2] is the size.
        !           544:  */
        !           545: lispval
        !           546: getvec(size,typestr,purep)
        !           547: register struct types *typestr;
        !           548: {
        !           549:     register lispval back, current;
        !           550:     int sizewant, bytes, thissize, pages, pindex, triedgc = FALSE;
        !           551: 
        !           552:     /* we have to round up to a multiple of 4 bytes to determine the
        !           553:      * size of vector we want.  The rounding up assures that the
        !           554:      * property pointers are longword aligned
        !           555:      */
        !           556:     sizewant = VecTotSize(size);
        !           557:     if(debugin) fprintf(stderr,"want vect %db\n",size);    
        !           558:  again:
        !           559:     if(purep)
        !           560:         back = (lispval) &(typestr->next_pure_free);
        !           561:     else
        !           562:         back = (lispval) &(typestr->next_free);
        !           563:     current = back->v.vector[0];
        !           564:     while(current !=  CNIL)
        !           565:     {
        !           566:        if(debugin)
        !           567:             fprintf(stderr,"next free size %db; ", current->vl.vectorl[-1]);
        !           568:        if ((thissize = VecTotSize(current->vl.vectorl[-1])) == sizewant)
        !           569:        {
        !           570:            if(debugin) fprintf(stderr,"exact match of size %d at 0x%x\n",
        !           571:                                4*thissize, &current->v.vector[1]);
        !           572:            back->v.vector[0]
        !           573:                = current->v.vector[0];/* change free pointer*/
        !           574:            current->v.vector[0] = nil; /* put nil in property */
        !           575:            /* to the user, vector begins one after property*/
        !           576:            return((lispval)&current->v.vector[1]);
        !           577:        }
        !           578:        else if (thissize >= sizewant + 3)
        !           579:        {
        !           580:            /* the reason that there is a `+ 3' instead of `+ 2'
        !           581:             * is that we don't want to leave a zero sized vector which
        !           582:             * isn't guaranteed to be followed by another vector
        !           583:             */
        !           584:            if(debugin)
        !           585:             fprintf(stderr,"breaking a %d vector into a ",
        !           586:                                        current->vl.vectorl[-1]);
        !           587: 
        !           588:            current->v.vector[1+sizewant+1]
        !           589:                        = current->v.vector[0];  /* free list pointer */
        !           590:            current->vl.vectorl[1+sizewant]
        !           591:                        = VecTotToByte(thissize - sizewant - 2);/*size info */
        !           592:            back->v.vector[0] = (lispval) &(current->v.vector[1+sizewant+1]);
        !           593:            current->vl.vectorl[-1] = size;
        !           594: 
        !           595:            if(debugin)fprintf(stderr," %d one and a %d one\n",
        !           596:                current->vl.vectorl[-1],current->vl.vectorl[1+sizewant]);
        !           597:            current->v.vector[0] = nil; /* put nil in property */
        !           598:            /* vector begins one after the property */
        !           599:            if(debugin) fprintf(stderr," and returning vector at 0x%x\n",
        !           600:                                &current->v.vector[1]);
        !           601:            return((lispval)(&current->v.vector[1]));
        !           602:        }
        !           603:        back =  current;
        !           604:        current =  current->v.vector[0];
        !           605:     }
        !           606:     if(!triedgc
        !           607:         && !purep
        !           608:        && (gcdis->a.clb == nil)
        !           609:        && (initflag == FALSE))
        !           610:     {
        !           611:        gc(typestr);
        !           612:        triedgc = TRUE;
        !           613:        goto again;
        !           614:     }
        !           615:     
        !           616:     /* set bytes to size needed for this vector */
        !           617:     bytes = size + 2*sizeof(long);
        !           618:     
        !           619:     /* must make sure that if the vector we are allocating doesnt
        !           620:        completely fill a page, there is room for another vector to record
        !           621:        the size left over */
        !           622:     if((bytes & (LBPG - 1)) > (LBPG - 2*sizeof(long))) bytes += LBPG;
        !           623:     bytes = roundup(bytes,LBPG);
        !           624: 
        !           625:     current = csegment(typestr->type,bytes/sizeof(long),purep);
        !           626:     current->vl.vectorl[0] = bytes - 2*sizeof(long);
        !           627:     
        !           628:     if(purep) {
        !           629:         current->v.vector[1] = (lispval)(typestr->next_pure_free);
        !           630:         typestr->next_pure_free = (char *) &(current->v.vector[1]);
        !           631:        /* make them pure */
        !           632:        pages = bytes/LBPG;
        !           633:        for(pindex = ATOX(current); pages ; pages--)
        !           634:        {
        !           635:            purepage[pindex++] = TRUE;
        !           636:        }
        !           637:     } else {
        !           638:         current->v.vector[1] = (lispval)(typestr->next_free);
        !           639:         typestr->next_free = (char *) &(current->v.vector[1]);
        !           640:        if(debugin) fprintf(stderr,"grabbed %d vec pages\n",bytes/LBPG);
        !           641:     }
        !           642:     if(debugin)
        !           643:       fprintf(stderr,"creating a new vec, size %d\n",current->v.vector[0]);
        !           644:     goto again;
        !           645: }
        !           646: 
        !           647: /*
        !           648:  * Ipurep :: routine to check for pureness of a data item
        !           649:  *
        !           650:  */
        !           651: lispval 
        !           652: Ipurep(element)
        !           653: lispval element;
        !           654: {
        !           655:     if(purepage[ATOX(element)]) return(tatom) ; else return(nil);
        !           656: }
        !           657: 
        !           658: /* routines to return space to the free list.  These are used by the
        !           659:  * arithmetic routines which tend to create large intermediate results
        !           660:  * which are know to be garbage after the calculation is over.
        !           661:  *
        !           662:  * There are jsb callable versions of these routines in qfuncl.s
        !           663:  */
        !           664: 
        !           665: /* pruneb   - prune bignum. A bignum is an sdot followed by a list of
        !           666:  *  dtprs.    The dtpr list is linked by car instead of cdr so when we
        !           667:  *  put it in the free list, we have to change the links.
        !           668:  */
        !           669: pruneb(bignum)
        !           670: lispval bignum;
        !           671: {
        !           672:        register lispval temp = bignum;
        !           673: 
        !           674:        if(TYPE(temp) != SDOT) 
        !           675:            errorh(Vermisc,"value to pruneb not a sdot",nil,FALSE,0);
        !           676: 
        !           677:        --(sdot_items->i);
        !           678:        temp->s.I = (int) sdot_str.next_free;
        !           679:        sdot_str.next_free = (char *) temp;
        !           680: 
        !           681:        /* bignums are not terminated by nil on the dual,
        !           682:           they are terminated by (lispval) 0 */
        !           683: 
        !           684:        while(temp = temp->s.CDR)
        !           685:        {
        !           686:            if(TYPE(temp) != DTPR) 
        !           687:              errorh(Vermisc,"value to pruneb not a list",
        !           688:                      nil,FALSE,0);
        !           689:            --(dtpr_items->i);
        !           690:            temp->s.I = (int) dtpr_str.next_free;
        !           691:            dtpr_str.next_free = (char *) temp;
        !           692:        }
        !           693: }
        !           694: lispval
        !           695: Badcall()
        !           696:        { error("BAD FUNCTION DESCRIPTOR USED IN CALL",FALSE); }
        !           697: 
        !           698: 
        !           699: 
        !           700: /*
        !           701:  * Ngc 
        !           702:  *  this is the lisp function gc
        !           703:  *
        !           704:  */
        !           705: 
        !           706: lispval
        !           707: Ngc()
        !           708: {
        !           709:     return(gc((struct types *)CNIL));
        !           710: }
        !           711: 
        !           712: /*
        !           713:  * gc(type_struct) 
        !           714:  *
        !           715:  *  garbage collector:  Collects garbage by mark and sweep algorithm.
        !           716:  *  After this is done, calls the Nlambda, gcafter.
        !           717:  *  gc may also be called from LISP, as an  nlambda of no arguments.
        !           718:  * type_struct is the type of lisp data that ran out causing this
        !           719:  * garbage collection
        !           720:  */
        !           721: int printall = 0;
        !           722: lispval
        !           723: gc(type_struct)
        !           724:        struct types *type_struct;
        !           725:        {
        !           726:        lispval save;
        !           727:        struct tms begin, finish;
        !           728:        extern int gctime;
        !           729: 
        !           730:        /* if this was called automatically when space ran out
        !           731:         * print out a message
        !           732:         */
        !           733:        if((Vgcprint->a.clb != nil)
        !           734:           && (type_struct != (struct types *) CNIL ))
        !           735:        {
        !           736:            FILE *port = okport(Vpoport->a.clb,poport);
        !           737:            fprintf(port,"gc:");
        !           738:            fflush(port);
        !           739:        }
        !           740:        
        !           741:        if(gctime) times(&begin);
        !           742: 
        !           743:        gc1(); /* mark&sweep */
        !           744: 
        !           745:        /* Now we call gcafter--special c ase if gc called from LISP */
        !           746: 
        !           747:        if( type_struct == (struct types *) CNIL )
        !           748:                gccall1->d.cdr = nil;  /* make the call "(gcafter)" */
        !           749:        else
        !           750:                {
        !           751:                gccall1->d.cdr = gccall2;
        !           752:                gccall2->d.car = *(type_struct->type_name);
        !           753:                }
        !           754:        PUSHDOWN(gcdis,gcdis);  /*  flag to indicate in garbage collector  */
        !           755:        save = eval(gccall1);   /*  call gcafter  */
        !           756:        POP;                    /*  turn off flag  */
        !           757: 
        !           758:        if(gctime) {
        !           759:                times(&finish);
        !           760:                gctime += (finish.tms_utime - begin.tms_utime);
        !           761:        }
        !           762:        return(save);   /*  return result of gcafter  */
        !           763:        }
        !           764: 
        !           765:        
        !           766: 
        !           767: /*  gc1()  **************************************************************/
        !           768: /*                                                                     */
        !           769: /*  Mark-and-sweep phase                                               */
        !           770: 
        !           771: gc1()
        !           772: {
        !           773:        int j, k;
        !           774:        register int *start,bvalue,type_len; 
        !           775:        register struct types *s;
        !           776:        int *point,i,freecnt,itemstogo,bits,bindex,type,bytestoclear;
        !           777:        int usedcnt;
        !           778:        char *pindex;
        !           779:        struct argent *loop2;
        !           780:        struct nament *loop3;
        !           781:        struct atom *symb;
        !           782:        int markdp();
        !           783:        extern int hashtop;
        !           784: 
        !           785:        pagerand(); 
        !           786:        /*  decide whether to check LISP structure or not  */
        !           787: 
        !           788: 
        !           789: #ifdef METER
        !           790:        vtimes(&premark,0);
        !           791:        mrkdpcnt = 0;
        !           792:        conssame = consdiff = consnil = 0;
        !           793: #endif
        !           794: 
        !           795:        /*  first set all bit maps to zero  */
        !           796: 
        !           797: 
        !           798: #ifdef SLOCLEAR
        !           799:        {
        !           800:            int enddat;
        !           801:            enddat = (int)(datalim-OFFSET) >> 8;
        !           802:            for(bvalue=0; bvalue < (int)enddat ; ++bvalue)
        !           803:            {
        !           804:                 qbitmap[bvalue] = zeroq; 
        !           805:            }
        !           806:        }
        !           807: #endif
        !           808: 
        !           809:        /* try the movc5 to clear the bit maps */
        !           810:        /* the maximum number of bytes we can clear in one sweep is
        !           811:         * 2^16 (or 1<<16 in the C lingo)
        !           812:         */
        !           813:        bytestoclear = ((((int)datalim)-((int)beginsweep)) >> 9) * 16; 
        !           814:        for(start = bitmapi + ATOLX(beginsweep);
        !           815:            bytestoclear > 0;)
        !           816:            {
        !           817:                if(bytestoclear > MAXCLEAR)
        !           818:                        blzero((int)start,MAXCLEAR);
        !           819:                else
        !           820:                        blzero((int)start,bytestoclear);
        !           821:                start = (int *) (MAXCLEAR + (int) start);
        !           822:                bytestoclear -= MAXCLEAR;
        !           823:            }
        !           824:                        
        !           825:        /* mark all atoms in the oblist */
        !           826:         for( bvalue=0 ; bvalue <= hashtop-1 ; bvalue++ ) /* though oblist */
        !           827:         {
        !           828:            for( symb = hasht[bvalue] ; symb != (struct atom *) CNIL ;
        !           829:                      symb = symb-> hshlnk) {
        !           830:                  markdp((lispval)symb); 
        !           831:            }
        !           832:        }
        !           833: 
        !           834: 
        !           835:        /* Mark all the atoms and ints associated with the hunk
        !           836:           data types */
        !           837:           
        !           838:        for(i=0; i<7; i++) {
        !           839:                markdp(hunk_items[i]);
        !           840:                markdp(hunk_name[i]);
        !           841:                markdp(hunk_pages[i]);
        !           842:        }
        !           843:        /* next run up the name stack */
        !           844:        for(loop2 = np - 1; loop2 >=  orgnp; --loop2) MARKVAL(loop2->val);      
        !           845: 
        !           846:        /* now the bindstack (vals only, atoms are marked elsewhere ) */
        !           847:        for(loop3 = bnp - 1; loop3 >= orgbnp; --loop3)MARKVAL(loop3->val);
        !           848: 
        !           849:        
        !           850:        /* next mark all compiler linked data */
        !           851:        /* if the Vpurcopylits switch is non nil (lisp variable $purcopylits)
        !           852:         * then when compiled code is read in, it tables will not be linked
        !           853:         * into this table and thus will not be marked here.  That is ok
        !           854:         * though, since that data is assumed to be pure.
        !           855:         */
        !           856:         point = bind_lists;
        !           857:         while((start = point) != (int *)CNIL) {
        !           858:                while( *start != -1 )
        !           859:                {
        !           860:                        markdp((lispval)*start);
        !           861:                        start++;
        !           862:                }
        !           863:                point = (int *)*(point-1);
        !           864:         }
        !           865: 
        !           866:        /* next mark all system-significant lisp data */
        !           867: 
        !           868:        
        !           869:        for(i=0; i<SIGNIF; ++i) markdp((lispsys[i]));
        !           870: 
        !           871: #ifdef METER
        !           872:        vtimes(&presweep,0);
        !           873: #endif
        !           874:        /* all accessible data has now been marked. */
        !           875:        /* all collectable spaces must be swept,    */
        !           876:        /* and freelists constructed.               */
        !           877: 
        !           878:        /* first clear the structure elements for types
        !           879:         * we will sweep
        !           880:         */
        !           881:        
        !           882:        for(k=0 ; k <= VECTORI ; k++)
        !           883:        {
        !           884:                if( s=gcableptr[k]) {
        !           885:                    if(k==STRNG && !gcstrings) { /* don't do anything*/ }
        !           886:                    else
        !           887:                        {
        !           888:                          (*(s->items))->i = 0;
        !           889:                          s->space_left = 0;
        !           890:                          s->next_free = (char *) CNIL;
        !           891:                        }
        !           892:                }
        !           893:        }
        !           894: #if m_68k
        !           895:        fixbits(bitmapi+ATOLX(beginsweep),bitmapi+ATOLX(datalim));
        !           896: #endif
        !           897: 
        !           898: 
        !           899:        /* sweep up in memory looking at gcable pages */
        !           900: 
        !           901:        for(start = beginsweep,  bindex = ATOLX(start), 
        !           902:                  pindex = &purepage[ATOX(start)]; 
        !           903:            start < (int *)datalim;
        !           904:            start += 128, pindex++)
        !           905:        {
        !           906:            if(!(s=gcableptr[type = TYPE(start)]) || *pindex
        !           907: #ifdef GCSTRINGS
        !           908:             || (type==STRNG && !gcstrings) 
        !           909: #endif
        !           910:                )
        !           911:            {
        !           912:                /* ignore this page but advance pointer         */
        !           913:                bindex += 4;   /* and 4 words of 32 bit bitmap words */
        !           914:                continue;
        !           915:            }
        !           916: 
        !           917:            freecnt = 0;                /* number of free items found */
        !           918:            usedcnt = 0;                /* number of used items found */
        !           919:            
        !           920:            point = start;
        !           921:            /* sweep dtprs as a special case, since
        !           922:             * 1) there will (usually) be more dtpr pages than any other type
        !           923:             * 2) most dtpr pages will be empty so we can really win by special
        !           924:             *    caseing the sweeping of massive numbers of free cells
        !           925:             */
        !           926:            /* since sdot's have the same structure as dtprs, this code will
        !           927:               work for them too
        !           928:             */
        !           929:            if((type == DTPR) || (type == SDOT))
        !           930:            {
        !           931:                int *head,*lim;
        !           932:                head = (int *) s->next_free;    /* first value on free list*/
        !           933: 
        !           934:                for(i=0; i < 4; i++)    /* 4 bit map words per page  */
        !           935:                {
        !           936:                    bvalue = bitmapi[bindex++]; /* 32 bits = 16 dtprs */
        !           937:                    if(bvalue == 0)     /* if all are free      */
        !           938:                    {
        !           939:                        *point = (int)head;
        !           940:                        lim = point + 32;   /* 16 dtprs = 32 ints */
        !           941:                        for(point += 2; point < lim ; point += 2)
        !           942:                        {
        !           943:                            *point = (int)(point - 2);
        !           944:                        }
        !           945:                        head = point - 2;
        !           946:                        freecnt += 16;
        !           947:                    }
        !           948:                    else for(j = 0; j < 16 ; j++)
        !           949:                    {
        !           950:                        if(!(bvalue & 1))
        !           951:                        {
        !           952:                            freecnt++;
        !           953:                            *point = (int)head;
        !           954:                            head = point;
        !           955:                        }
        !           956: #ifdef METER
        !           957:                        /* check if the page address of this cell is the
        !           958:                         * same as the address of its cdr
        !           959:                         */
        !           960:                        else if(FALSE && gcstat && (type == DTPR))
        !           961:                        {  
        !           962:                           if(((int)point & ~511) 
        !           963:                              == ((int)(*point) & ~511)) conssame++;
        !           964:                           else consdiff++;
        !           965:                           usedcnt++;
        !           966:                        }
        !           967: #endif
        !           968:                        else usedcnt++;         /* keep track of used */
        !           969:                        
        !           970:                        point += 2;
        !           971:                        bvalue = bvalue >> 2;
        !           972:                    }
        !           973:                }
        !           974:                s->next_free = (char *) head;
        !           975:            }
        !           976:            else if((type == VECTOR) || (type == VECTORI))
        !           977:            {
        !           978:                int canjoin = FALSE;
        !           979:                int *tempp;
        !           980: 
        !           981:                /* check if first item on freelist ends exactly at
        !           982:                   this page
        !           983:                 */
        !           984:                if(((tempp = (int *)s->next_free) != (int *)CNIL)
        !           985:                   && ((VecTotSize(((lispval)tempp)->vl.vectorl[-1])
        !           986:                                                            + 1 + tempp)
        !           987:                                        == point))
        !           988:                   canjoin = TRUE;
        !           989:                   
        !           990:                /* arbitrary sized vector sweeper */
        !           991:                /*
        !           992:                 * jump past first word since that is a size fixnum
        !           993:                 * and second word since that is property word
        !           994:                 */
        !           995:                if(debugin)
        !           996:                  fprintf(stderr,"vector sweeping, start at 0x%x\n",
        !           997:                                point);
        !           998:                bits = 30;
        !           999:                bvalue = bitmapi[bindex++] >> 2;
        !          1000:                point += 2;
        !          1001:                while (TRUE) {
        !          1002:                    type_len = point[VSizeOff];
        !          1003:                    if(debugin) {
        !          1004:                      fprintf(stderr,"point: 0x%x, type_len %d\n",
        !          1005:                                point, type_len);
        !          1006:                      fprintf(stderr,"bvalue: 0x%x, bits: %d, bindex: 0x%x\n",
        !          1007:                                bvalue, bits, bindex);
        !          1008:                    }
        !          1009:                                        /* get size of vector */
        !          1010:                    if(!(bvalue & 1))   /* if free */
        !          1011:                    {
        !          1012:                        if(debugin) fprintf(stderr,"free\n");
        !          1013:                        freecnt += type_len + 2*sizeof(long);
        !          1014:                        if(canjoin)
        !          1015:                        {
        !          1016:                            /* join by adjusting size of first vector */
        !          1017:                            ((lispval)(s->next_free))->vl.vectorl[-1]
        !          1018:                              +=  type_len + 2*sizeof(long); 
        !          1019:                            if(debugin)
        !          1020:                              fprintf(stderr,"joined size: %d\n",
        !          1021:                                  ((lispval)(s->next_free))->vl.vectorl[-1]);
        !          1022:                        }
        !          1023:                        else {
        !          1024:                            /* vectors are linked at the property word */
        !          1025:                            *(point - 1) = (int)(s->next_free);
        !          1026:                            s->next_free = (char *) (point - 1);
        !          1027:                        }
        !          1028:                        canjoin = TRUE;
        !          1029:                    }
        !          1030:                    else {
        !          1031:                        canjoin = FALSE;
        !          1032:                        usedcnt += type_len + 2*sizeof(long);
        !          1033:                    }
        !          1034:                    
        !          1035:                    point += VecTotSize(type_len);
        !          1036:                    /* we stop sweeping only when we reach a page
        !          1037:                       boundary since vectors can span pages
        !          1038:                     */
        !          1039:                    if(((int)point & 511) == 0)
        !          1040:                    {
        !          1041:                        /* reset the counters, we cannot predict how
        !          1042:                         * many pages we have crossed over
        !          1043:                         */
        !          1044:                        bindex = ATOLX(point);
        !          1045:                        /* these will be inced, so we must dec */
        !          1046:                        pindex = &purepage[ATOX(point)] - 1;
        !          1047:                        start = point - 128;
        !          1048:                        if(debugin)
        !          1049:                        fprintf(stderr,
        !          1050:                                "out of vector sweep when point = 0x%x\n",
        !          1051:                                point);
        !          1052:                        break;
        !          1053:                    }
        !          1054:                    /* must advance to next point and next value in bitmap.
        !          1055:                     * we add VecTotSize(type_len) + 2 to get us to the 0th
        !          1056:                     * entry in the next vector (beyond the size fixnum)
        !          1057:                     */
        !          1058:                    point += 2;         /* point to next 0th entry */
        !          1059:                    if ( (bits -= (VecTotSize(type_len) + 2)) > 0)  
        !          1060:                        bvalue = bvalue >> (VecTotSize(type_len) + 2);
        !          1061:                    else {
        !          1062:                        bits = -bits;   /* must advance to next word in map */
        !          1063:                        bindex += bits / 32; /* this is tricky stuff... */
        !          1064:                        bits = bits % 32;
        !          1065:                        bvalue = bitmapi[bindex++] >> bits;
        !          1066:                        bits = 32 - bits;
        !          1067:                    }
        !          1068:                }
        !          1069:            }
        !          1070:            else { 
        !          1071:                /* general sweeper, will work for all types */
        !          1072:                itemstogo = s->space;   /* number of items per page  */
        !          1073:                bits = 32;                      /* number of bits per word */
        !          1074:                type_len = s->type_len;
        !          1075: 
        !          1076:                /* printf(" s %d, itemstogo %d, len %d\n",s,itemstogo,type_len);*/
        !          1077:                bvalue = bitmapi[bindex++];
        !          1078: 
        !          1079:                while(TRUE)
        !          1080:                {
        !          1081:                    if(!(bvalue & 1))   /* if data element is not marked */
        !          1082:                    {
        !          1083:                        freecnt++;
        !          1084:                        *point = (int) (s->next_free) ;
        !          1085:                        s->next_free = (char *) point;
        !          1086:                    }
        !          1087:                    else usedcnt++;
        !          1088: 
        !          1089:                    if( --itemstogo <= 0 ) 
        !          1090:                    {    if(type_len >= 64) 
        !          1091:                         {
        !          1092:                            bindex++;
        !          1093:                            if(type_len >=128) bindex += 2;
        !          1094:                         }
        !          1095:                         break;
        !          1096:                    }
        !          1097: 
        !          1098:                    point += type_len;
        !          1099:                    /* shift over mask by number of words in data type */
        !          1100: 
        !          1101:                    if( (bits -= type_len) > 0)
        !          1102:                    {  bvalue = bvalue >> type_len;
        !          1103:                    } 
        !          1104:                    else if( bits == 0 ) 
        !          1105:                    {  bvalue = bitmapi[bindex++];
        !          1106:                       bits = 32;
        !          1107:                    }
        !          1108:                    else
        !          1109:                    {  bits = -bits;
        !          1110:                       while( bits >= 32) { bindex++;
        !          1111:                                            bits -= 32;
        !          1112:                                          }
        !          1113:                       bvalue = bitmapi[bindex++];
        !          1114:                       bvalue = bvalue >> bits;
        !          1115:                       bits = 32 - bits;;
        !          1116:                    }
        !          1117:            }
        !          1118:        }
        !          1119: 
        !          1120:      s->space_left += freecnt;
        !          1121:      (*(s->items))->i += usedcnt;
        !          1122:      }
        !          1123: 
        !          1124: #ifdef METER
        !          1125:         vtimes(&alldone,0);
        !          1126:        if(gcstat) gcdump();
        !          1127: #endif
        !          1128:        pagenorm(); 
        !          1129: }
        !          1130: 
        !          1131: /*
        !          1132:  * alloc
        !          1133:  *
        !          1134:  *  This routine tries to allocate one or more pages of the space named
        !          1135:  *  by the first argument.   Returns the number of pages actually allocated.
        !          1136:  *  
        !          1137:  */
        !          1138: 
        !          1139: lispval
        !          1140: alloc(tname,npages)
        !          1141: lispval tname; long npages;
        !          1142: {
        !          1143:        long ii, jj;
        !          1144:        struct types *typeptr;
        !          1145: 
        !          1146:        ii = typenum(tname);
        !          1147:         typeptr = spaces[ii];
        !          1148:        if(npages <= 0) return(inewint(npages));
        !          1149:        
        !          1150:        if((ATOX(datalim)) + npages > TTSIZE)
        !          1151:           error("Space request would exceed maximum memory allocation",FALSE);
        !          1152:        if((ii == VECTOR) || (ii == VECTORI))
        !          1153:        {
        !          1154:            /* allocate in one big chunk */
        !          1155:            tname = csegment((int) ii,(int) npages*128,0);
        !          1156:            tname->vl.vectorl[0] = (npages*512 - 2*sizeof(long));
        !          1157:            tname->v.vector[1] = (lispval) typeptr->next_free;
        !          1158:            typeptr->next_free = (char *) &(tname->v.vector[1]);
        !          1159:            if(debugin) fprintf(stderr,"alloced %d vec pages\n",npages);
        !          1160:            return(inewint(npages));
        !          1161:        }
        !          1162:           
        !          1163:        for( jj=0; jj<npages; ++jj)
        !          1164:                if(get_more_space(spaces[ii],FALSE)) break;
        !          1165:        return(inewint(jj));
        !          1166: }
        !          1167: 
        !          1168: /*
        !          1169:  * csegment(typecode,nitems,useholeflag)
        !          1170:  *  allocate nitems of type typecode.  If useholeflag is true, then
        !          1171:  * allocate in the hole if there is room.  This routine doesn't look
        !          1172:  * in the free lists, it always allocates space.
        !          1173:  */    
        !          1174: lispval
        !          1175: csegment(typecode,nitems,useholeflag)
        !          1176: {
        !          1177:        register int ii, jj;
        !          1178:        register char *charadd;
        !          1179: 
        !          1180:        ii = typecode;
        !          1181: 
        !          1182:        if(ii!=OTHER) nitems *= 4*spaces[ii]->type_len;
        !          1183:        nitems = roundup(nitems,512);           /*  round up to right length  */
        !          1184: #ifdef HOLE
        !          1185:        if(useholeflag)
        !          1186:                charadd = gethspace(nitems,ii);
        !          1187:        else
        !          1188: #endif
        !          1189:        {
        !          1190:                charadd = sbrk(nitems);
        !          1191:                datalim = (lispval)(charadd+nitems);
        !          1192:        }
        !          1193:        if( (int) charadd <= 0 )
        !          1194:                error("NOT ENOUGH SPACE FOR ARRAY",FALSE);
        !          1195:        /*if(ii!=OTHER)*/ (*spaces[ii]->pages)->i +=  nitems/512;
        !          1196:        if(ATOX(datalim) > fakettsize) {
        !          1197:                datalim = (lispval) (OFFSET + (fakettsize << 9));
        !          1198:                if(fakettsize >= TTSIZE)
        !          1199:                {
        !          1200:                    printf("There isn't room enough to continue, goodbye\n");
        !          1201:                    franzexit(1);
        !          1202:                }
        !          1203:                fakettsize++;
        !          1204:                badmem(53);
        !          1205:        }
        !          1206:        for(jj=0; jj<nitems; jj=jj+512) {
        !          1207:                SETTYPE(charadd+jj, ii,30);
        !          1208:        }
        !          1209:        ii = (int) charadd;
        !          1210:        while(nitems > MAXCLEAR)
        !          1211:        {
        !          1212:            blzero(ii,MAXCLEAR);
        !          1213:            nitems -= MAXCLEAR;
        !          1214:            ii += MAXCLEAR;
        !          1215:        }
        !          1216:        blzero(ii,nitems);
        !          1217:        return((lispval)charadd);
        !          1218: }
        !          1219: 
        !          1220: int csizeof(tname) lispval tname;
        !          1221:        {
        !          1222:        return( spaces[typenum(tname)]->type_len * 4 );
        !          1223:        }
        !          1224: 
        !          1225: int typenum(tname) lispval tname;
        !          1226:        {
        !          1227:        int ii;
        !          1228: 
        !          1229: chek:  for(ii=0; ii<NUMSPACES; ++ii)
        !          1230:                if(spaces[ii] && tname == *(spaces[ii]->type_name)) break;
        !          1231:        if(ii == NUMSPACES)
        !          1232:                {
        !          1233:                tname = error("BAD TYPE NAME",TRUE);
        !          1234:                goto chek;
        !          1235:                }
        !          1236: 
        !          1237:        return(ii);
        !          1238:        
        !          1239:        }
        !          1240: char *
        !          1241: gethspace(segsiz,type)
        !          1242: {
        !          1243:        extern usehole; extern char holend[]; extern char *curhbeg;
        !          1244:        register char *value;
        !          1245: 
        !          1246:        if(usehole) {   
        !          1247:                curhbeg = (char *) roundup(((int)curhbeg),LBPG);
        !          1248:                if((holend - curhbeg) < segsiz)
        !          1249:                {       
        !          1250:                        usehole = FALSE;
        !          1251:                        curhbeg = holend;
        !          1252:                } else {
        !          1253:                        value = curhbeg;
        !          1254:                        curhbeg = curhbeg + segsiz;
        !          1255:                        /*printf("start %d, finish %d, size %d\n",value, curhbeg,segsiz);*/
        !          1256:                        return(value);
        !          1257:                }
        !          1258:        }
        !          1259:        value = (ysbrk(segsiz/LBPG,type));
        !          1260:        datalim = (lispval)(value + segsiz);
        !          1261:        return(value);
        !          1262: }
        !          1263: gcrebear()
        !          1264: {
        !          1265: #ifdef HOLE
        !          1266:         register int i; register struct types *p;
        !          1267: 
        !          1268:        /* this gets done upon rebirth */
        !          1269:        str_current[1].space_left = 0;
        !          1270: #ifndef GCSTRINGS
        !          1271:        str_current[0].space_left = 0;  /* both kinds of strings go in hole*/
        !          1272: #endif
        !          1273:        funct_str.space_left = 0;
        !          1274:        funct_str.next_free = (char *) CNIL;
        !          1275:        /* clear pure space pointers */
        !          1276:        for(i = 0; i < NUMSPACES; i++)
        !          1277:        {
        !          1278:            if(p=spaces[i])
        !          1279:            p->next_pure_free = (char *) CNIL;
        !          1280:        }
        !          1281: #endif
        !          1282: }
        !          1283: 
        !          1284: /** markit(p) ***********************************************************/
        !          1285: /*  just calls markdp                                                  */
        !          1286: 
        !          1287: markit(p) lispval *p; { markdp(*p); }
        !          1288: 
        !          1289: /*
        !          1290:  * markdp(p)
        !          1291:  *
        !          1292:  *  markdp is the routine which marks each data item.  If it is a
        !          1293:  *  dotted pair, the car and cdr are marked also.
        !          1294:  *  An iterative method is used to mark list structure, to avoid
        !          1295:  *  excessive recursion.
        !          1296:  */
        !          1297: markdp(p) register lispval p;
        !          1298:        {
        !          1299: #ifdef tahoe
        !          1300:        register int r, s;      /* (goes with non-asm readbit, oksetbit) */
        !          1301: #endif
        !          1302: /*     register hsize, hcntr;                                           */
        !          1303:        int hsize, hcntr;
        !          1304: 
        !          1305: #ifdef METER
        !          1306:        mrkdpcnt++;
        !          1307: #endif
        !          1308: ptr_loop:
        !          1309:        if(((int)p) <= ((int)nil)) return;      /*  do not mark special data types or nil=0  */
        !          1310: 
        !          1311:                
        !          1312:        switch( TYPE(p) )
        !          1313:                {
        !          1314:                case ATOM:
        !          1315:                        ftstbit;
        !          1316:                        MARKVAL(p->a.clb);
        !          1317:                        MARKVAL(p->a.plist);
        !          1318:                        MARKVAL(p->a.fnbnd);
        !          1319: #ifdef GCSTRINGS
        !          1320:                        if(gcstrings) MARKVAL(((lispval)p->a.pname));
        !          1321:                        return;
        !          1322: 
        !          1323:                case STRNG:
        !          1324:                        p = (lispval) (((int) p) & ~ (LBPG-1));
        !          1325:                        ftstbit;
        !          1326: #endif
        !          1327:                        return;
        !          1328:                        
        !          1329:                case INT:
        !          1330:                case DOUB:
        !          1331:                        ftstbit;
        !          1332:                        return;
        !          1333:                case VALUE:
        !          1334:                        ftstbit;
        !          1335:                        p = p->l;
        !          1336:                        goto ptr_loop;
        !          1337:                case DTPR:
        !          1338:                        ftstbit;
        !          1339:                        MARKVAL(p->d.car);
        !          1340: #ifdef METER
        !          1341:                        /* if we are metering , then check if the cdr is
        !          1342:                         * nil, or if the cdr is on the same page, and if
        !          1343:                         * it isn't one of those, then it is on a different
        !          1344:                         * page
        !          1345:                         */
        !          1346:                         if(gcstat)
        !          1347:                         {
        !          1348:                             if(p->d.cdr == nil) consnil++;
        !          1349:                             else if(((int)p & ~511) 
        !          1350:                                     == (((int)(p->d.cdr)) & ~511))
        !          1351:                                conssame++;
        !          1352:                             else consdiff++;
        !          1353:                          }
        !          1354: #endif
        !          1355:                        p = p->d.cdr;
        !          1356:                        goto ptr_loop;
        !          1357: 
        !          1358:                case ARRAY:
        !          1359:                        ftstbit;        /* mark array itself */
        !          1360: 
        !          1361:                        MARKVAL(p->ar.accfun);  /* mark access function */
        !          1362:                        MARKVAL(p->ar.aux);             /* mark aux data */
        !          1363:                        MARKVAL(p->ar.length);  /* mark length */
        !          1364:                        MARKVAL(p->ar.delta);   /* mark delta */
        !          1365:                        if(TYPE(p->ar.aux)==DTPR && p->ar.aux->d.car==Vnogbar)
        !          1366:                        {
        !          1367:                            /* a non garbage collected array must have its
        !          1368:                             * array space marked but the value of the array
        !          1369:                             * space is not marked
        !          1370:                             */
        !          1371:                             int l; 
        !          1372:                             int cnt,d;
        !          1373:                             if(debugin) {
        !          1374:                               printf("mark array holders len %d, del %d, start 0x%x\n",
        !          1375:                                 p->ar.length->i,p->ar.delta->i,p->ar.data);
        !          1376:                                 fflush(stdout);
        !          1377:                            }
        !          1378:                             l = p->ar.length->i; /* number of elements */
        !          1379:                             d = p->ar.delta->i;  /* bytes per element  */
        !          1380:                             p = (lispval) p->ar.data;/* address of first one*/
        !          1381:                             if(purepage[ATOX(p)]) return;
        !          1382: 
        !          1383:                             for((cnt = 0); cnt<l ; 
        !          1384:                                      p = (lispval)(((char *) p) + d), cnt++)
        !          1385:                             {
        !          1386:                                setbit;
        !          1387:                             }
        !          1388:                        } else {
        !          1389: /*                     register int i, l; int d;               */
        !          1390: /*                     register char *dataptr = p->ar.data;    */
        !          1391:                        int i,l,d;
        !          1392:                        char *dataptr = p->ar.data;
        !          1393: 
        !          1394:                        for(i=0, l=p->ar.length->i, d=p->ar.delta->i; i<l; ++i)
        !          1395:                                {
        !          1396:                                markdp((lispval)dataptr);
        !          1397:                                dataptr += d;
        !          1398:                                }
        !          1399:                        }
        !          1400:                        return;
        !          1401:                case SDOT:
        !          1402:                        do {
        !          1403:                                ftstbit;
        !          1404:                                p = p->s.CDR;
        !          1405:                        } while (p!=0);
        !          1406:                        return;
        !          1407: 
        !          1408:                case BCD:
        !          1409:                        ftstbit;
        !          1410:                        markdp(p->bcd.discipline);
        !          1411:                        return;
        !          1412: 
        !          1413:                case HUNK2:
        !          1414:                case HUNK4:
        !          1415:                case HUNK8:
        !          1416:                case HUNK16:
        !          1417:                case HUNK32:
        !          1418:                case HUNK64:
        !          1419:                case HUNK128:
        !          1420:                        {
        !          1421:                                hsize = 2 << HUNKSIZE(p);
        !          1422:                                ftstbit;
        !          1423:                                for (hcntr = 0; hcntr < hsize; hcntr++)
        !          1424:                                        MARKVAL(p->h.hunk[hcntr]);
        !          1425:                                return;
        !          1426:                        }
        !          1427:                        
        !          1428:                case VECTORI:
        !          1429:                        ftstbit;
        !          1430:                        MARKVAL(p->v.vector[-1]);       /* mark property */
        !          1431:                        return;
        !          1432:                        
        !          1433:                case VECTOR:
        !          1434:                        {
        !          1435:                            register int vsize;
        !          1436:                            ftstbit;
        !          1437:                            vsize = VecSize(p->vl.vectorl[VSizeOff]);
        !          1438:                            if(debugin)
        !          1439:                               fprintf(stderr,"mark vect at %x  size %d\n",
        !          1440:                                        p,vsize);
        !          1441:                            while(--vsize >= -1)
        !          1442:                            {
        !          1443:                                MARKVAL(p->v.vector[vsize]);
        !          1444:                            };
        !          1445:                            return;
        !          1446:                        }
        !          1447:                }
        !          1448:        return;
        !          1449:        }
        !          1450: 
        !          1451: 
        !          1452: /* xsbrk allocates space in large chunks (currently 16 pages)
        !          1453:  * xsbrk(1)  returns a pointer to a page
        !          1454:  * xsbrk(0)  returns a pointer to the next page we will allocate (like sbrk(0))
        !          1455:  */
        !          1456: 
        !          1457: char *
        !          1458: xsbrk(n)
        !          1459:        {
        !          1460:        static char *xx;        /*  pointer to next available blank page  */
        !          1461:        extern int xcycle;      /*  number of blank pages available  */
        !          1462:        lispval u;                      /*  used to compute limits of bit table  */
        !          1463: 
        !          1464:        if( (xcycle--) <= 0 )
        !          1465:                {
        !          1466:                xcycle = 15;
        !          1467:                xx = sbrk(16*LBPG);     /*  get pages 16 at a time  */
        !          1468:                if( (int)xx== -1 )
        !          1469:                        lispend("For sbrk from lisp: no space... Goodbye!");
        !          1470:                }
        !          1471:        else xx += LBPG;
        !          1472: 
        !          1473:        if(n == 0)
        !          1474:        {
        !          1475:            xcycle++;   /* don't allocate the page */
        !          1476:            xx -= LBPG;
        !          1477:            return(xx); /* just return its address */
        !          1478:        }
        !          1479: 
        !          1480:        if( (u = (lispval)(xx+LBPG))  > datalim ) datalim = u;
        !          1481:        return(xx);
        !          1482:        }
        !          1483: 
        !          1484: char *ysbrk(pages,type) int pages, type;
        !          1485:        {
        !          1486:        char *xx;       /*  will point to block of storage  */
        !          1487:        int i;
        !          1488: 
        !          1489:        xx = sbrk(pages*LBPG);
        !          1490:        if((int)xx == -1)
        !          1491:                error("OUT OF SPACE FOR ARRAY REQUEST",FALSE);
        !          1492: 
        !          1493:        datalim = (lispval)(xx+pages*LBPG);     /*  compute bit table limit  */
        !          1494: 
        !          1495:        /*  set type for pages  */
        !          1496: 
        !          1497:        for(i = 0; i < pages; ++i) {
        !          1498:                SETTYPE((xx + i*LBPG),type,10);
        !          1499:        }
        !          1500: 
        !          1501:        return(xx);     /*  return pointer to block of storage  */
        !          1502:        }
        !          1503:        
        !          1504: /*
        !          1505:  * getatom 
        !          1506:  * returns either an existing atom with the name specified in strbuf, or
        !          1507:  * if the atom does not already exist, regurgitates a new one and 
        !          1508:  * returns it.
        !          1509:  */
        !          1510: lispval
        !          1511: getatom(purep)
        !          1512: {   register lispval aptr;
        !          1513:     register char *name, *endname;
        !          1514:     register int hash;
        !          1515:     lispval    b;
        !          1516:     char       c;
        !          1517: 
        !          1518:        name = strbuf;
        !          1519:        if (*name == (char)0377) return (eofa);
        !          1520:        hash = hashfcn(name);
        !          1521:        atmlen = strlen(name) + 1;
        !          1522:        aptr = (lispval) hasht[hash];
        !          1523:        while (aptr != CNIL)
        !          1524:            /* if (strcmp(name,aptr->a.pname)==0) */
        !          1525:            if (*name==*aptr->a.pname && strcmp(name,aptr->a.pname)==0)
        !          1526:                return (aptr);
        !          1527:            else
        !          1528:                aptr = (lispval) aptr->a.hshlnk;
        !          1529:        aptr = (lispval) newatom(purep);  /*share pname of atoms on oblist*/
        !          1530:        aptr->a.hshlnk = hasht[hash];
        !          1531:        hasht[hash] = (struct atom *) aptr;
        !          1532:        endname = name + atmlen - 2;
        !          1533:        if ((atmlen != 4) && (*name == 'c') && (*endname == 'r'))
        !          1534:                {
        !          1535:                b = newdot();
        !          1536:                protect(b);
        !          1537:                b->d.car = lambda;
        !          1538:                b->d.cdr = newdot();
        !          1539:                b = b->d.cdr;
        !          1540:                b->d.car = newdot();
        !          1541:                (b->d.car)->d.car = xatom;
        !          1542:                while(TRUE)
        !          1543:                        {
        !          1544:                        b->d.cdr = newdot();
        !          1545:                        b= b->d.cdr;
        !          1546:                        if(++name == endname)
        !          1547:                                {
        !          1548:                                b->d.car= (lispval) xatom;
        !          1549:                                aptr->a.fnbnd = (--np)->val;
        !          1550:                                break;
        !          1551:                                }
        !          1552:                        b->d.car= newdot();
        !          1553:                        b= b->d.car;
        !          1554:                        if((c = *name) == 'a') b->d.car = cara;
        !          1555:                        else if (c == 'd') b->d.car = cdra;
        !          1556:                        else{ --np;
        !          1557:                           break;
        !          1558:                         }
        !          1559:                        }
        !          1560:                }
        !          1561: 
        !          1562:        return(aptr);
        !          1563:        }
        !          1564: 
        !          1565: /*
        !          1566:  * inewatom is like getatom, except that you provide it a string
        !          1567:  * to be used as the print name.  It doesn't do the automagic
        !          1568:  * creation of things of the form c[ad]*r.
        !          1569:  */
        !          1570: lispval
        !          1571: inewatom(name)
        !          1572: register char *name;
        !          1573: {   register struct atom *aptr;
        !          1574:     register int hash;
        !          1575:     extern struct types atom_str;
        !          1576:     char       c;
        !          1577: 
        !          1578:        if (*name == (char)0377) return (eofa);
        !          1579:        hash = hashfcn(name);
        !          1580:        aptr = hasht[hash];
        !          1581:        while (aptr != (struct atom *)CNIL)
        !          1582:            if (strcmp(name,aptr->pname)==0)
        !          1583:                return ((lispval) aptr);
        !          1584:            else
        !          1585:                aptr = aptr->hshlnk;
        !          1586:        aptr = (struct atom *) next_one(&atom_str) ;    
        !          1587:        aptr->plist = aptr->fnbnd = nil;
        !          1588:        aptr->clb = CNIL;
        !          1589:        aptr->pname = name;
        !          1590:        aptr->hshlnk = hasht[hash];
        !          1591:        hasht[hash] = aptr;
        !          1592:        return((lispval)aptr);
        !          1593: }
        !          1594: 
        !          1595: 
        !          1596: /* our hash function */
        !          1597: 
        !          1598: hashfcn(symb)
        !          1599: register char *symb;
        !          1600: {
        !          1601:        register int i;
        !          1602: /*     for (i=0 ; *symb ; i += i + *symb++); return(i & (HASHTOP-1)); */
        !          1603:        for (i=0 ; *symb ; i += i*2 + *symb++);
        !          1604:        return(i&077777 % HASHTOP);
        !          1605: }
        !          1606: 
        !          1607: lispval
        !          1608: LImemory()
        !          1609: {
        !          1610:     int nextadr, pagesinuse;
        !          1611:     
        !          1612:     printf("Memory report. max pages = %d (0x%x) = %d Bytes\n",
        !          1613:                TTSIZE,TTSIZE,TTSIZE*LBPG);
        !          1614: #ifdef HOLE
        !          1615:         printf("This lisp has a hole:\n");
        !          1616:        printf("  current hole start: %d (0x%x), end %d (0x%x)\n",
        !          1617:                curhbeg, curhbeg, holend, holend);
        !          1618:        printf("  hole free: %d bytes = %d pages\n\n",
        !          1619:               holend-curhbeg, (holend-curhbeg)/LBPG);
        !          1620: #endif 
        !          1621:     nextadr = (int) xsbrk(0);  /* next space to be allocated */
        !          1622:     pagesinuse = nextadr/LBPG;
        !          1623:     printf("Next allocation at addr %d (0x%x) = page %d\n",
        !          1624:                        nextadr, nextadr, pagesinuse);
        !          1625:     printf("Free data pages: %d\n", TTSIZE-pagesinuse);
        !          1626:     return(nil);
        !          1627: }
        !          1628: 
        !          1629: extern struct atom *hasht[HASHTOP];
        !          1630: myhook(){}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.