Annotation of researchv10no/cmd/dag/kpvmalloc.c, revision 1.1.1.1

1.1       root        1: /**********************************************************************
                      2:        Memory management: malloc(), realloc(), free().
                      3: 
                      4:        Kiem-Phong Vo, ulysses!kpv,
                      5:        AT&T Bell Laboratories, MH5D102, 201-582-4869.
                      6: 
                      7:        The following #-parameters may be redefined:
                      8:        SEGMENTED: if defined, memory requests are assumed to be
                      9:                non-contiguous across calls of GETCORE's.
                     10:        GETCORE: a function to get more core memory. If not SEGMENTED,
                     11:                GETCORE(0) is assumed to return the next available
                     12:                address. Default is 'sbrk'.
                     13:        ERRCORE: the error code as returned by GETCORE.
                     14:                Default is ((char *)(-1)).
                     15:        CORESIZE: a desired unit (measured in bytes) to be used
                     16:                with GETCORE. Default is (1024*ALIGN).
                     17: 
                     18:        This algorithm is based on a  best fit strategy with lists of
                     19:        free elts maintained in a self-adjusting binary tree. Each list
                     20:        contains all elts of the same size. The tree is ordered by size.
                     21:        For results on self-adjusting trees, see the paper:
                     22:                Self-Adjusting Binary Trees,
                     23:                DD Sleator & RE Tarjan, JACM 1985.
                     24: 
                     25:        The header of a block contains the size of the data part in bytes.
                     26:        Since the size of a block is 0%4, the low two bits of the header
                     27:        are free and used as follows:
                     28: 
                     29:                BIT0:   1 for busy (block is in use), 0 for free.
                     30:                BIT1:   if the block is busy, this bit is 1 if the
                     31:                        preceding block in contiguous memory is free.
                     32:                        Otherwise, it is always 0.
                     33: **********************************************************************/
                     34: 
                     35: /* debugging macros */
                     36: #ifdef DEBUG
                     37: #define        ASSERT(p)       if(!(p))abort()
                     38: #define COUNT(n)       n++
                     39: static int             nmalloc, nrealloc, nfree;
                     40: #else
                     41: #define        ASSERT(p)
                     42: #define COUNT(n)
                     43: #endif /*DEBUG*/
                     44: 
                     45: /* function to copy data from one area to another */
                     46: #ifdef SYSV
                     47: #define memcopy(to,fr,n)       memcpy(to,fr,n)
                     48: #endif
                     49: 
                     50: #ifdef BSD
                     51: #define memcopy(to,fr,n)       bcopy(fr,to,n)
                     52: #endif
                     53: 
                     54: #ifndef memcopy
                     55: static memcopy(to,fr,n)
                     56: register char  *to, *fr;
                     57: register int   n;
                     58: {
                     59:        for(; n > 0; --n)
                     60:                *to++ = *fr++;
                     61: }
                     62: #endif
                     63: 
                     64: /* for conveniences */
                     65: #define reg            register
                     66: #define NULL           (0)
                     67: #define WORDSIZE       ((int)(sizeof(WORD)))
                     68: #define MINSIZE                ((int)(sizeof(TREE)-sizeof(WORD)))
                     69: #define ROUND(s)       if(s%WORDSIZE) s += (WORDSIZE - (s%WORDSIZE))
                     70: 
                     71: #ifdef DEBUG32
                     72: /* The following definitions ease debugging
                     73: ** on a machine in which sizeof(pointer) == sizeof(int) == 4.
                     74: ** These definitions are not portable.
                     75: */
                     76: #define        ALIGN   4
                     77: typedef int    WORD;
                     78: typedef struct _t_
                     79: {
                     80:        unsigned int    t_s;
                     81:        struct _t_      *t_p;
                     82:        struct _t_      *t_l;
                     83:        struct _t_      *t_r;
                     84:        struct _t_      *t_n;
                     85:        struct _t_      *t_d;
                     86: }      TREE;
                     87: #define SIZE(b)                ((b)->t_s)
                     88: #define AFTER(b)       ((b)->t_p)
                     89: #define PARENT(b)      ((b)->t_p)
                     90: #define LEFT(b)                ((b)->t_l)
                     91: #define RIGHT(b)       ((b)->t_r)
                     92: #define LINKFOR(b)     ((b)->t_n)
                     93: #define LINKBAK(b)     ((b)->t_p)
                     94: 
                     95: #else  /* !DEBUG32 */
                     96: /* The following definitions assume that "char *" has the largest size
                     97: ** among all pointer types. If this is not true, PTRSIZE should
                     98: ** be redefined to be the size of the largest pointer type (void * ?).
                     99: ** All of our allocations will be aligned on the least multiple of 4
                    100: ** that is >= PTRSIZE.
                    101: */
                    102: #define PTRSIZE                ((int)(sizeof(char *)))
                    103: #define ALIGN          (PTRSIZE%4 ? PTRSIZE+(4-(PTRSIZE%4)) : PTRSIZE)
                    104: 
                    105: /* the proto-word */
                    106: typedef union _w_
                    107: {
                    108:        unsigned int    w_i;            /* an int */
                    109:        struct _t_      *w_p;           /* a pointer */
                    110:        char            w_a[ALIGN];     /* to force alignment */
                    111: } WORD;
                    112: 
                    113: /* structure of a node in the free tree */
                    114: typedef struct _t_
                    115: {
                    116:        WORD    t_s;    /* size of this element */
                    117:        WORD    t_p;    /* parent node */
                    118:        WORD    t_l;    /* left child */
                    119:        WORD    t_r;    /* right child */
                    120:        WORD    t_n;    /* next in link list */
                    121:        WORD    t_d;    /* dummy to reserve space for self-pointer */
                    122: } TREE;
                    123: 
                    124: /* usable # of bytes in the block */
                    125: #define SIZE(b)                (((b)->t_s).w_i)
                    126: 
                    127: /* free tree pointers */
                    128: #define PARENT(b)      (((b)->t_p).w_p)
                    129: #define LEFT(b)                (((b)->t_l).w_p)
                    130: #define RIGHT(b)       (((b)->t_r).w_p)
                    131: 
                    132: /* forward link in lists of small blocks */
                    133: #define AFTER(b)       (((b)->t_p).w_p)
                    134: 
                    135: /* forward and backward links for lists in the tree */
                    136: #define LINKFOR(b)     (((b)->t_n).w_p)
                    137: #define LINKBAK(b)     (((b)->t_p).w_p)
                    138: 
                    139: #endif /* DEBUG32 */
                    140: 
                    141: /* set/test indicator if a block is in the tree or in a list */
                    142: #define SETNOTREE(b)   (LEFT(b) = (TREE *)(-1))
                    143: #define ISNOTREE(b)    (LEFT(b) == (TREE *)(-1))
                    144: 
                    145: /* functions to get information on a block */
                    146: #define DATA(b)                (((char *) (b)) + WORDSIZE)
                    147: #define BLOCK(d)       ((TREE *) ((d) - WORDSIZE))
                    148: #define SELFP(b)       ((TREE **) (((char *) (b)) + SIZE(b)))
                    149: #define LAST(b)                (*((TREE **) (((char *) (b)) - WORDSIZE)))
                    150: #define NEXT(b)                ((TREE *) (((char *) (b)) + SIZE(b) + WORDSIZE))
                    151: #define BOTTOM(b)      ((DATA(b)+SIZE(b)+WORDSIZE) == Baddr)
                    152: 
                    153: /* functions to set and test the lowest two bits of a word */
                    154: #define        BIT0            (01)    /* ....01 */
                    155: #define BIT1           (02)    /* ...010 */
                    156: #define BITS01         (03)    /* ...011 */
                    157: #define ISBIT0(w)      ((w) & BIT0)
                    158: #define ISBIT1(w)      ((w) & BIT1)
                    159: #define        SETBIT0(w)      ((w) |= BIT0)
                    160: #define SETBIT1(w)     ((w) |= BIT1)
                    161: #define CLRBIT0(w)     ((w) &= ~BIT0)
                    162: #define CLRBIT1(w)     ((w) &= ~BIT1)
                    163: #define SETBITS01(w)   ((w) |= BITS01)
                    164: #define CLRBITS01(w)   ((w) &= ~BITS01)
                    165: 
                    166: /* system call to get more core */
                    167: #define GETCORE                sbrk
                    168: #define ERRCORE                ((char *)(-1))
                    169: #define CORESIZE       (1024*ALIGN)
                    170: 
                    171: static TREE    *Root,          /* root of the free tree */
                    172:                *Bottom,        /* the last free chunk in the arena */
                    173:                *_morecore();   /* function to get more core */
                    174: 
                    175: static char    *Baddr;         /* current high address of the arena */
                    176: 
                    177: char   *GETCORE(), *malloc(), *realloc();
                    178: 
                    179: 
                    180: /*
                    181: **     Allocation of small blocks
                    182: */
                    183: 
                    184: static TREE    *List[MINSIZE/WORDSIZE]; /* lists of small blocks */
                    185: 
                    186: static char *  _smalloc(size)
                    187: unsigned int   size;
                    188: {
                    189:        reg TREE        *tp, *np;
                    190:        reg int         i, n;
                    191: 
                    192:        /* nothing to do */
                    193:        if(size == 0)
                    194:                return NULL;
                    195: 
                    196:        /* list to use */
                    197:        i = size/WORDSIZE - 1;
                    198: 
                    199:        if(List[i] == NULL)
                    200:        {
                    201:        /* number of blocks to get at one time */
                    202: #define NPS (WORDSIZE*8)
                    203:        /**/ASSERT((size+WORDSIZE)*NPS >= MINSIZE);
                    204: 
                    205:                /* get NPS of these block types */
                    206:                if((List[i] = (TREE *) malloc((size+WORDSIZE)*NPS)) == NULL)
                    207:                        return NULL;
                    208: 
                    209:                /* make them into a link list */
                    210:                for(n = 0, np = List[i]; n < NPS; ++n)
                    211:                {
                    212:                        tp = np;
                    213:                        SIZE(tp) = size;
                    214:                        np = NEXT(tp);
                    215:                        AFTER(tp) = np;
                    216:                }
                    217:                AFTER(tp) = NULL;
                    218:        }
                    219: 
                    220:        /* allocate from the head of the queue */
                    221:        tp = List[i];
                    222:        List[i] = AFTER(tp);
                    223:        SETBIT0(SIZE(tp));
                    224:        return DATA(tp);
                    225: }
                    226: 
                    227: 
                    228: 
                    229: /*
                    230: **     malloc().
                    231: */
                    232: char * malloc(size)
                    233: unsigned int   size;
                    234: {
                    235:        reg int         n;
                    236:        reg TREE        *tp, *sp;
                    237: 
                    238:        /**/ COUNT(nmalloc);
                    239:        /**/ ASSERT(WORDSIZE == ALIGN);
                    240: 
                    241:        /* make sure that size is 0 mod ALIGN */
                    242:        ROUND(size);
                    243: 
                    244:        /* small blocks */
                    245:        if(size < MINSIZE)
                    246:                return _smalloc(size);
                    247: 
                    248:        /* search for an elt of the right size */
                    249:        sp = NULL;
                    250:        n  = -1;
                    251:        if(Root)
                    252:        {
                    253:                tp = Root;
                    254:                while(1)
                    255:                {
                    256:                        /* branch left */
                    257:                        if(SIZE(tp) >= size)
                    258:                        {
                    259:                                if(n < 0 || n >= SIZE(tp))
                    260:                                        sp = tp, n = SIZE(tp);
                    261:                                if(LEFT(tp))
                    262:                                        tp = LEFT(tp);
                    263:                                else    break;
                    264:                        }
                    265:                        else
                    266:                        { /* branch right */
                    267:                                if(RIGHT(tp))
                    268:                                        tp = RIGHT(tp);
                    269:                                else    break;
                    270:                        }
                    271:                }
                    272: 
                    273:                if(sp)
                    274:                {
                    275:                        t_delete(sp);
                    276:                }
                    277:                else if(tp != Root)
                    278:                {
                    279:                        /* make the searched-to element the root */
                    280:                        t_splay(tp);
                    281:                        Root = tp;
                    282:                }
                    283:        }
                    284: 
                    285:        /* if found none fitted in the tree */
                    286:        if(!sp)
                    287:        {
                    288:                if(Bottom && size <= SIZE(Bottom))
                    289:                        sp = Bottom;
                    290:                else    sp = _morecore(size);
                    291: 
                    292:                /* no more memory */
                    293:                if(!sp)
                    294:                        return NULL;
                    295:        }
                    296: 
                    297:        /* tell the forward neighbor that we're busy */
                    298:        CLRBIT1(SIZE(NEXT(sp)));        /**/ ASSERT(ISBIT0(SIZE(NEXT(sp))));
                    299: 
                    300:        /* if the leftover is enough for a new free piece */
                    301:        if((n = (SIZE(sp) - size) - WORDSIZE) >= MINSIZE)
                    302:        {
                    303:                SIZE(sp) = size;
                    304:                tp = NEXT(sp);
                    305:                SIZE(tp) = n|BIT0;
                    306:                free(DATA(tp));
                    307:        }
                    308:        else if(BOTTOM(sp))
                    309:                Bottom = NULL;
                    310: 
                    311:        /* return the allocated space */
                    312:        SETBIT0(SIZE(sp));
                    313:        return DATA(sp);
                    314: }
                    315: 
                    316: 
                    317: /*
                    318: **     realloc().
                    319: **     If the block size is increasing, we try forward merging first.
                    320: **     This is not best-fit but it avoids some data recopying.
                    321: */
                    322: char * realloc(old,size)
                    323: char           *old;
                    324: unsigned int   size;
                    325: {
                    326:        reg TREE        *tp, *np;
                    327:        reg int         n, ts;
                    328:        reg char        *new;
                    329: 
                    330:        /**/ COUNT(nrealloc);
                    331: 
                    332:        /* make sure that size is 0 mod ALIGN */
                    333:        ROUND(size);
                    334: 
                    335:        /* pointer to the block */
                    336:        tp = BLOCK(old);
                    337:        ts = SIZE(tp);
                    338: 
                    339:        /* if the block was freed, data has been destroyed. */
                    340:        if(!ISBIT0(ts))
                    341:                return NULL;
                    342: 
                    343:        /* nothing to do */
                    344:        CLRBITS01(SIZE(tp));
                    345:        if(size == SIZE(tp))
                    346:        {
                    347:                SIZE(tp) = ts;
                    348:                return old;
                    349:        }
                    350: 
                    351:        /* special cases involving small blocks */
                    352:        if(size < MINSIZE || SIZE(tp) < MINSIZE)
                    353:                goto call_malloc;
                    354: 
                    355:        /* block is increasing in size, try merging the next block */
                    356:        if(size > SIZE(tp))
                    357:        {
                    358:                np = NEXT(tp);
                    359:                if(!ISBIT0(SIZE(np)))
                    360:                {
                    361:                        /**/ ASSERT(SIZE(np) >= MINSIZE);
                    362:                        /**/ ASSERT(!ISBIT1(SIZE(np)));
                    363:                        SIZE(tp) += SIZE(np)+WORDSIZE;
                    364:                        if(np != Bottom)
                    365:                                t_delete(np);
                    366:                        else    Bottom = NULL;
                    367:                        CLRBIT1(SIZE(NEXT(np)));
                    368:                }
                    369: 
                    370: #ifndef SEGMENTED
                    371:                /* not enough & at TRUE end of memory, try extending core */
                    372:                if(size > SIZE(tp) && BOTTOM(tp) && GETCORE(0) == Baddr)
                    373:                {
                    374:                        Bottom = tp;
                    375:                        _morecore(size);
                    376:                }
                    377: #endif /*!SEGMENTED*/
                    378:        }
                    379: 
                    380:        /* got enough space to use */
                    381:        if(size <= SIZE(tp))
                    382:        {
                    383:                if((n = (SIZE(tp) - size) - WORDSIZE) >= MINSIZE)
                    384:                {
                    385:                        SIZE(tp) = size;
                    386:                        np = NEXT(tp);
                    387:                        SIZE(np) = n|BIT0;
                    388:                        free(DATA(np));
                    389:                }
                    390:                else if(BOTTOM(tp))
                    391:                        Bottom = NULL;
                    392: 
                    393:                /* the previous block may be free */
                    394:                if(ISBIT1(ts))
                    395:                        SETBIT1(SIZE(tp));
                    396:                SETBIT0(SIZE(tp));
                    397:                return old;
                    398:        }
                    399: 
                    400:        /* call malloc to get a new block */
                    401: call_malloc:
                    402:        SETBIT0(SIZE(tp));
                    403:        if(ISBIT1(ts))
                    404:                SETBIT1(SIZE(tp));
                    405:        if((new = malloc(size)) != NULL)
                    406:        {
                    407:                ts = SIZE(tp);
                    408:                CLRBITS01(ts);
                    409:                memcopy(new,old,ts < size ? ts : size);
                    410:        }
                    411:        free(old);
                    412:        return new;
                    413: }
                    414: 
                    415: 
                    416: 
                    417: /*
                    418: **     free().
                    419: **     Coalescing of adjacent free blocks is done first.
                    420: **     Then, the new free block is leaf-inserted into the free tree
                    421: **     without splaying. This strategy does not guarantee the amortized
                    422: **     O(nlogn) behaviour for the insert/delete/find set of operations
                    423: **     on the tree. In practice, however, free is much more infrequent
                    424: **     than malloc/realloc and the tree searches performed by these
                    425: **     functions adequately keep the tree in balance.
                    426: */
                    427: free(old)
                    428: char   *old;
                    429: {
                    430:        reg TREE        *tp, *sp, *np;
                    431:        reg int         ts, size;
                    432: 
                    433:        /**/ COUNT(nfree);
                    434: 
                    435:        /* pointer to the block */
                    436:        tp = BLOCK(old);
                    437:        ts = SIZE(tp);
                    438:        if(!ISBIT0(ts))
                    439:                return -1;
                    440:        CLRBITS01(SIZE(tp));
                    441: 
                    442:        /* small block, put it in the right linked list */
                    443:        if(SIZE(tp) < MINSIZE)
                    444:        {
                    445:                ts = SIZE(tp)/WORDSIZE - 1;
                    446:                AFTER(tp) = List[ts];
                    447:                List[ts] = tp;
                    448:                return 0;
                    449:        }
                    450: 
                    451:        /* see if coalescing with next block is warranted */
                    452:        np = NEXT(tp);
                    453:        if(!ISBIT0(SIZE(np)))
                    454:        {
                    455:                if(np != Bottom)
                    456:                        t_delete(np);
                    457:                SIZE(tp) += SIZE(np)+WORDSIZE;
                    458:        }
                    459: 
                    460:        /* the same with the preceding block */
                    461:        if(ISBIT1(ts))
                    462:        {
                    463:                np = LAST(tp);          /**/ ASSERT(!ISBIT0(SIZE(np)));
                    464:                                        /**/ ASSERT(np != Bottom);
                    465:                t_delete(np);
                    466:                SIZE(np) += SIZE(tp)+WORDSIZE;
                    467:                tp = np;
                    468:        }
                    469: 
                    470:        /* initialize tree info */
                    471:        PARENT(tp) = LEFT(tp) = RIGHT(tp) = LINKFOR(tp) = NULL;
                    472: 
                    473:        /* the last word of the block contains self's address */
                    474:        *(SELFP(tp)) = tp;
                    475: 
                    476:        /* set bottom block, or insert in the free tree */
                    477:        if(BOTTOM(tp))
                    478:                Bottom = tp;
                    479:        else
                    480:        {
                    481:                /* search for the place to insert */
                    482:                if(Root)
                    483:                {
                    484:                        size = SIZE(tp);
                    485:                        np = Root;
                    486:                        while(1)
                    487:                        {
                    488:                                if(SIZE(np) > size)
                    489:                                {
                    490:                                        if(LEFT(np))
                    491:                                                np = LEFT(np);
                    492:                                        else
                    493:                                        {
                    494:                                                LEFT(np) = tp;
                    495:                                                PARENT(tp) = np;
                    496:                                                break;
                    497:                                        }
                    498:                                }
                    499:                                else if(SIZE(np) < size)
                    500:                                {
                    501:                                        if(RIGHT(np))
                    502:                                                np = RIGHT(np);
                    503:                                        else
                    504:                                        {
                    505:                                                RIGHT(np) = tp;
                    506:                                                PARENT(tp) = np;
                    507:                                                break;
                    508:                                        }
                    509:                                }
                    510:                                else
                    511:                                {
                    512:                                        if(sp = PARENT(np))     /* assignment = */
                    513:                                        {
                    514:                                                if(np == LEFT(sp))
                    515:                                                        LEFT(sp) = tp;
                    516:                                                else    RIGHT(sp) = tp;
                    517:                                                PARENT(tp) = sp;
                    518:                                        }
                    519:                                        else    Root = tp;
                    520: 
                    521:                                        /* insert to head of list */
                    522:                                        if(sp = LEFT(np))       /* assignment = */
                    523:                                                PARENT(sp) = tp;
                    524:                                        LEFT(tp) = sp;
                    525: 
                    526:                                        if(sp = RIGHT(np))      /* assignment = */
                    527:                                                PARENT(sp) = tp;
                    528:                                        RIGHT(tp) = sp;
                    529: 
                    530:                                        /* doubly link list */
                    531:                                        LINKFOR(tp) = np;
                    532:                                        LINKBAK(np) = tp;
                    533:                                        SETNOTREE(np);
                    534: 
                    535:                                        break;
                    536:                                }
                    537:                        }
                    538:                }
                    539:                else    Root = tp;
                    540:        }
                    541: 
                    542:        /* tell next block that this one is free */
                    543:        SETBIT1(SIZE(NEXT(tp)));        /**/ ASSERT(ISBIT0(SIZE(NEXT(tp))));
                    544: 
                    545:        return 0;
                    546: }
                    547: 
                    548: 
                    549: 
                    550: /*
                    551: **     Get more core. Gaps in memory are noted as busy blocks.
                    552: */
                    553: static TREE *  _morecore(size)
                    554: unsigned int   size;
                    555: {
                    556:        reg TREE        *tp;
                    557:        reg int         n;
                    558:        reg char        *addr;
                    559: 
                    560:        /* compute new amount of memory to get */
                    561:        tp = Bottom;
                    562:        n = size + 2*WORDSIZE;
                    563: 
                    564: #ifndef SEGMENTED
                    565:        /* if not segmented memory, what we need may be smaller */
                    566:        if((addr = GETCORE(0)) == Baddr)
                    567:                n = (size - (tp ? SIZE(tp) : 0)) + WORDSIZE;
                    568: #endif /*!SEGMENTED*/
                    569: 
                    570:        /* get a multiple of CORESIZE */
                    571:        n = (n/CORESIZE + 1) * CORESIZE;
                    572:        if((addr = GETCORE(n)) == ERRCORE)
                    573:                return NULL;
                    574: 
                    575:        /* contiguous memory */
                    576:        if(addr == Baddr)
                    577:        {
                    578:                if(tp)
                    579:                {
                    580:                        addr = ((char *)tp);
                    581:                        n += SIZE(tp) + 2*WORDSIZE;
                    582:                }
                    583:                else
                    584:                {
                    585:                        addr = Baddr-WORDSIZE;
                    586:                        n += WORDSIZE;
                    587:                }
                    588:        }
                    589: 
                    590:        /* new bottom address */
                    591:        Baddr = addr + n;
                    592: 
                    593:        /* new bottom block */
                    594:        tp = ((TREE *) addr);
                    595:        SIZE(tp) = n - 2*WORDSIZE;      /**/ASSERT((SIZE(tp)%ALIGN) == 0);
                    596: 
                    597:        /* reserved the last word to head any noncontiguous memory */
                    598:        SETBIT0(SIZE(NEXT(tp)));
                    599: 
                    600:        /* non-contiguous memory, free old bottom block */
                    601:        if(Bottom && Bottom != tp)
                    602:        {
                    603:                SETBIT0(SIZE(Bottom));
                    604:                free(DATA(Bottom));
                    605:        }
                    606: 
                    607:        return tp;
                    608: }
                    609: 
                    610: 
                    611: 
                    612: /*
                    613: **     Tree rotation functions (BU: bottom-up, TD: top-down)
                    614: */
                    615: 
                    616: #define LEFT1(x,y)     if((RIGHT(x) = LEFT(y))) PARENT(RIGHT(x)) = x;\
                    617:                        if((PARENT(y) = PARENT(x)))\
                    618:                                if(LEFT(PARENT(x)) == x) LEFT(PARENT(y)) = y;\
                    619:                                else RIGHT(PARENT(y)) = y;\
                    620:                        LEFT(y) = x; PARENT(x) = y
                    621: 
                    622: #define RIGHT1(x,y)    if((LEFT(x) = RIGHT(y))) PARENT(LEFT(x)) = x;\
                    623:                        if((PARENT(y) = PARENT(x)))\
                    624:                                if(LEFT(PARENT(x)) == x) LEFT(PARENT(y)) = y;\
                    625:                                else RIGHT(PARENT(y)) = y;\
                    626:                        RIGHT(y) = x; PARENT(x) = y
                    627: 
                    628: #define BULEFT2(x,y,z) if((RIGHT(x) = LEFT(y))) PARENT(RIGHT(x)) = x;\
                    629:                        if((RIGHT(y) = LEFT(z))) PARENT(RIGHT(y)) = y;\
                    630:                        if((PARENT(z) = PARENT(x)))\
                    631:                                if(LEFT(PARENT(x)) == x) LEFT(PARENT(z)) = z;\
                    632:                                else RIGHT(PARENT(z)) = z;\
                    633:                        LEFT(z) = y; PARENT(y) = z; LEFT(y) = x; PARENT(x) = y
                    634: 
                    635: #define BURIGHT2(x,y,z)        if((LEFT(x) = RIGHT(y))) PARENT(LEFT(x)) = x;\
                    636:                        if((LEFT(y) = RIGHT(z))) PARENT(LEFT(y)) = y;\
                    637:                        if((PARENT(z) = PARENT(x)))\
                    638:                                if(LEFT(PARENT(x)) == x) LEFT(PARENT(z)) = z;\
                    639:                                else RIGHT(PARENT(z)) = z;\
                    640:                        RIGHT(z) = y; PARENT(y) = z; RIGHT(y) = x; PARENT(x) = y
                    641: 
                    642: #define TDLEFT2(x,y,z) if((RIGHT(y) = LEFT(z))) PARENT(RIGHT(y)) = y;\
                    643:                        if((PARENT(z) = PARENT(x)))\
                    644:                                if(LEFT(PARENT(x)) == x) LEFT(PARENT(z)) = z;\
                    645:                                else RIGHT(PARENT(z)) = z;\
                    646:                        PARENT(x) = z; LEFT(z) = x;
                    647: 
                    648: #define TDRIGHT2(x,y,z)        if((LEFT(y) = RIGHT(z))) PARENT(LEFT(y)) = y;\
                    649:                        if((PARENT(z) = PARENT(x)))\
                    650:                                if(LEFT(PARENT(x)) == x) LEFT(PARENT(z)) = z;\
                    651:                                else RIGHT(PARENT(z)) = z;\
                    652:                        PARENT(x) = z; RIGHT(z) = x;
                    653: 
                    654: 
                    655: 
                    656: /*
                    657: **     Delete a tree element
                    658: */
                    659: static t_delete(op)
                    660: TREE   *op;
                    661: {
                    662:        reg TREE        *tp, *sp, *gp;
                    663: 
                    664:        /* if this is a non-tree node */
                    665:        if(ISNOTREE(op))
                    666:        {
                    667:                tp = LINKBAK(op);
                    668:                if(sp = LINKFOR(op))    /* assignment = */
                    669:                        LINKBAK(sp) = tp;
                    670:                LINKFOR(tp) = sp;
                    671:                return;
                    672:        }
                    673: 
                    674:        /* make op the root of the tree */
                    675:        if(PARENT(op))
                    676:                t_splay(op);
                    677: 
                    678:        /* if this is the start of a list */
                    679:        if(tp = LINKFOR(op))    /* assignment = */
                    680:        {
                    681:                PARENT(tp) = NULL;
                    682:                if(sp = LEFT(op))       /* assignment = */
                    683:                        PARENT(sp) = tp;
                    684:                LEFT(tp) = sp;
                    685: 
                    686:                if(sp = RIGHT(op))      /* assignment = */
                    687:                        PARENT(sp) = tp;
                    688:                RIGHT(tp) = sp;
                    689: 
                    690:                Root = tp;
                    691:                return;
                    692:        }
                    693: 
                    694:        /* if op has a non-null left subtree */
                    695:        if(tp = LEFT(op))       /* assignment = */
                    696:        {
                    697:                PARENT(tp) = NULL;
                    698: 
                    699:                if(RIGHT(op))
                    700:                {
                    701:                        /* make the right-end of the left subtree its root */
                    702:                        for(sp = RIGHT(tp); sp != NULL; sp = RIGHT(tp))
                    703:                        {
                    704:                                if(gp = RIGHT(sp))      /* assignment = */
                    705:                                {
                    706:                                        TDLEFT2(tp,sp,gp);
                    707:                                        tp = gp;
                    708:                                }
                    709:                                else
                    710:                                {
                    711:                                        LEFT1(tp,sp);
                    712:                                        tp = sp;
                    713:                                }
                    714:                        }
                    715: 
                    716:                        /* hook the right subtree of op to the above elt */
                    717:                        RIGHT(tp) = RIGHT(op);
                    718:                        PARENT(RIGHT(tp)) = tp;
                    719:                }
                    720:        }
                    721: 
                    722:        /* no left subtree */
                    723:        else if(tp = RIGHT(op))         /* assignment = */
                    724:                PARENT(tp) = NULL;
                    725: 
                    726:        Root = tp;
                    727: }
                    728: 
                    729: 
                    730: 
                    731: /*
                    732: **     Bottom up splaying (simple version).
                    733: **     The basic idea is to roughly cut in half the
                    734: **     path from Root to tp and make tp the new root.
                    735: */
                    736: static t_splay(tp)
                    737: reg TREE       *tp;
                    738: {
                    739:        reg TREE        *pp, *gp;
                    740: 
                    741:        /* iterate until tp is the root */
                    742:        for(pp = PARENT(tp); pp != NULL; pp = PARENT(tp))
                    743:        {
                    744:                /* grandparent of tp */
                    745:                gp = PARENT(pp);
                    746: 
                    747:                /* x is a left child */
                    748:                if(LEFT(pp) == tp)      
                    749:                {
                    750:                        if(gp && LEFT(gp) == pp)
                    751:                        {
                    752:                                BURIGHT2(gp,pp,tp);
                    753:                        }
                    754:                        else
                    755:                        {
                    756:                                RIGHT1(pp,tp);
                    757:                        }
                    758:                }
                    759:                else
                    760:                {               /**/ ASSERT(RIGHT(pp) == tp);
                    761:                        if(gp && RIGHT(gp) == pp)
                    762:                        {
                    763:                                BULEFT2(gp,pp,tp);
                    764:                        }
                    765:                        else
                    766:                        {
                    767:                                LEFT1(pp,tp);
                    768:                        }
                    769:                }
                    770:        }
                    771: } 

unix.superglobalmegacorp.com

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