Annotation of embedaddon/quagga/isisd/dict.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Dictionary Abstract Data Type
                      3:  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
                      4:  *
                      5:  * Free Software License:
                      6:  *
                      7:  * All rights are reserved by the author, with the following exceptions:
                      8:  * Permission is granted to freely reproduce and distribute this software,
                      9:  * possibly in exchange for a fee, provided that this copyright notice appears
                     10:  * intact. Permission is also granted to adapt this software to produce
                     11:  * derivative works, as long as the modified versions carry this copyright
                     12:  * notice and additional notices stating that the work has been modified.
                     13:  * This source code may be translated into executable form and incorporated
                     14:  * into proprietary software; there is no requirement for such software to
                     15:  * contain a copyright notice related to this source.
                     16:  */
                     17: 
                     18: #include <stdlib.h>
                     19: #include <stddef.h>
                     20: #include "zebra.h"
                     21: #include "zassert.h"
                     22: #define DICT_IMPLEMENTATION
                     23: #include "dict.h"
                     24: 
                     25: #ifdef KAZLIB_RCSID
                     26: static const char rcsid[] = "Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz";
                     27: #endif
                     28: 
                     29: /*
                     30:  * These macros provide short convenient names for structure members,
                     31:  * which are embellished with dict_ prefixes so that they are
                     32:  * properly confined to the documented namespace. It's legal for a 
                     33:  * program which uses dict to define, for instance, a macro called ``parent''.
                     34:  * Such a macro would interfere with the dnode_t struct definition.
                     35:  * In general, highly portable and reusable C modules which expose their
                     36:  * structures need to confine structure member names to well-defined spaces.
                     37:  * The resulting identifiers aren't necessarily convenient to use, nor
                     38:  * readable, in the implementation, however!
                     39:  */
                     40: 
                     41: #define left dict_left
                     42: #define right dict_right
                     43: #define parent dict_parent
                     44: #define color dict_color
                     45: #define key dict_key
                     46: #define data dict_data
                     47: 
                     48: #define nilnode dict_nilnode
                     49: #define nodecount dict_nodecount
                     50: #define maxcount dict_maxcount
                     51: #define compare dict_compare
                     52: #define allocnode dict_allocnode
                     53: #define freenode dict_freenode
                     54: #define context dict_context
                     55: #define dupes dict_dupes
                     56: 
                     57: #define dictptr dict_dictptr
                     58: 
                     59: #define dict_root(D) ((D)->nilnode.left)
                     60: #define dict_nil(D) (&(D)->nilnode)
                     61: #define DICT_DEPTH_MAX 64
                     62: 
                     63: static dnode_t *dnode_alloc(void *context);
                     64: static void dnode_free(dnode_t *node, void *context);
                     65: 
                     66: /*
                     67:  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
                     68:  * its right child C are rearranged so that the P instead becomes the left
                     69:  * child of C.   The left subtree of C is inherited as the new right subtree
                     70:  * for P.  The ordering of the keys within the tree is thus preserved.
                     71:  */
                     72: 
                     73: static void rotate_left(dnode_t *upper)
                     74: {
                     75:     dnode_t *lower, *lowleft, *upparent;
                     76: 
                     77:     lower = upper->right;
                     78:     upper->right = lowleft = lower->left;
                     79:     lowleft->parent = upper;
                     80: 
                     81:     lower->parent = upparent = upper->parent;
                     82: 
                     83:     /* don't need to check for root node here because root->parent is
                     84:        the sentinel nil node, and root->parent->left points back to root */
                     85: 
                     86:     if (upper == upparent->left) {
                     87:        upparent->left = lower;
                     88:     } else {
                     89:        assert (upper == upparent->right);
                     90:        upparent->right = lower;
                     91:     }
                     92: 
                     93:     lower->left = upper;
                     94:     upper->parent = lower;
                     95: }
                     96: 
                     97: /*
                     98:  * This operation is the ``mirror'' image of rotate_left. It is
                     99:  * the same procedure, but with left and right interchanged.
                    100:  */
                    101: 
                    102: static void rotate_right(dnode_t *upper)
                    103: {
                    104:     dnode_t *lower, *lowright, *upparent;
                    105: 
                    106:     lower = upper->left;
                    107:     upper->left = lowright = lower->right;
                    108:     lowright->parent = upper;
                    109: 
                    110:     lower->parent = upparent = upper->parent;
                    111: 
                    112:     if (upper == upparent->right) {
                    113:        upparent->right = lower;
                    114:     } else {
                    115:        assert (upper == upparent->left);
                    116:        upparent->left = lower;
                    117:     }
                    118: 
                    119:     lower->right = upper;
                    120:     upper->parent = lower;
                    121: }
                    122: 
                    123: /*
                    124:  * Do a postorder traversal of the tree rooted at the specified
                    125:  * node and free everything under it.  Used by dict_free().
                    126:  */
                    127: 
                    128: static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
                    129: {
                    130:     if (node == nil)
                    131:        return;
                    132:     free_nodes(dict, node->left, nil);
                    133:     free_nodes(dict, node->right, nil);
                    134:     dict->freenode(node, dict->context);
                    135: }
                    136: 
                    137: /*
                    138:  * This procedure performs a verification that the given subtree is a binary
                    139:  * search tree. It performs an inorder traversal of the tree using the
                    140:  * dict_next() successor function, verifying that the key of each node is
                    141:  * strictly lower than that of its successor, if duplicates are not allowed,
                    142:  * or lower or equal if duplicates are allowed.  This function is used for
                    143:  * debugging purposes. 
                    144:  */
                    145: 
                    146: static int verify_bintree(dict_t *dict)
                    147: {
                    148:     dnode_t *first, *next;
                    149: 
                    150:     first = dict_first(dict);
                    151: 
                    152:     if (dict->dupes) {
                    153:        while (first && (next = dict_next(dict, first))) {
                    154:            if (dict->compare(first->key, next->key) > 0)
                    155:                return 0;
                    156:            first = next;
                    157:        }
                    158:     } else {
                    159:        while (first && (next = dict_next(dict, first))) {
                    160:            if (dict->compare(first->key, next->key) >= 0)
                    161:                return 0;
                    162:            first = next;
                    163:        }
                    164:     }
                    165:     return 1;
                    166: }
                    167: 
                    168: 
                    169: /*
                    170:  * This function recursively verifies that the given binary subtree satisfies
                    171:  * three of the red black properties. It checks that every red node has only
                    172:  * black children. It makes sure that each node is either red or black. And it
                    173:  * checks that every path has the same count of black nodes from root to leaf.
                    174:  * It returns the blackheight of the given subtree; this allows blackheights to
                    175:  * be computed recursively and compared for left and right siblings for
                    176:  * mismatches. It does not check for every nil node being black, because there
                    177:  * is only one sentinel nil node. The return value of this function is the
                    178:  * black height of the subtree rooted at the node ``root'', or zero if the
                    179:  * subtree is not red-black.
                    180:  */
                    181: 
                    182: static unsigned int verify_redblack(dnode_t *nil, dnode_t *root)
                    183: {
                    184:     unsigned height_left, height_right;
                    185: 
                    186:     if (root != nil) {
                    187:        height_left = verify_redblack(nil, root->left);
                    188:        height_right = verify_redblack(nil, root->right);
                    189:        if (height_left == 0 || height_right == 0)
                    190:            return 0;
                    191:        if (height_left != height_right)
                    192:            return 0;
                    193:        if (root->color == dnode_red) {
                    194:            if (root->left->color != dnode_black)
                    195:                return 0;
                    196:            if (root->right->color != dnode_black)
                    197:                return 0;
                    198:            return height_left;
                    199:        }
                    200:        if (root->color != dnode_black)
                    201:            return 0;
                    202:        return height_left + 1;
                    203:     } 
                    204:     return 1;
                    205: }
                    206: 
                    207: /*
                    208:  * Compute the actual count of nodes by traversing the tree and
                    209:  * return it. This could be compared against the stored count to
                    210:  * detect a mismatch.
                    211:  */
                    212: 
                    213: static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root)
                    214: {
                    215:     if (root == nil)
                    216:        return 0;
                    217:     else
                    218:        return 1 + verify_node_count(nil, root->left)
                    219:            + verify_node_count(nil, root->right);
                    220: }
                    221: 
                    222: /*
                    223:  * Verify that the tree contains the given node. This is done by
                    224:  * traversing all of the nodes and comparing their pointers to the
                    225:  * given pointer. Returns 1 if the node is found, otherwise
                    226:  * returns zero. It is intended for debugging purposes.
                    227:  */
                    228: 
                    229: static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
                    230: {
                    231:     if (root != nil) {
                    232:        return root == node
                    233:                || verify_dict_has_node(nil, root->left, node)
                    234:                || verify_dict_has_node(nil, root->right, node);
                    235:     }
                    236:     return 0;
                    237: }
                    238: 
                    239: 
                    240: /*
                    241:  * Dynamically allocate and initialize a dictionary object.
                    242:  */
                    243: 
                    244: dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp)
                    245: {
                    246:     dict_t *new = malloc(sizeof *new);
                    247: 
                    248:     if (new) {
                    249:        new->compare = comp;
                    250:        new->allocnode = dnode_alloc;
                    251:        new->freenode = dnode_free;
                    252:        new->context = NULL;
                    253:        new->nodecount = 0;
                    254:        new->maxcount = maxcount;
                    255:        new->nilnode.left = &new->nilnode;
                    256:        new->nilnode.right = &new->nilnode;
                    257:        new->nilnode.parent = &new->nilnode;
                    258:        new->nilnode.color = dnode_black;
                    259:        new->dupes = 0;
                    260:     }
                    261:     return new;
                    262: }
                    263: 
                    264: /*
                    265:  * Select a different set of node allocator routines.
                    266:  */
                    267: 
                    268: void dict_set_allocator(dict_t *dict, dnode_alloc_t al,
                    269:        dnode_free_t fr, void *context)
                    270: {
                    271:     assert (dict_count(dict) == 0);
                    272:     assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL));
                    273: 
                    274:     dict->allocnode = al ? al : dnode_alloc;
                    275:     dict->freenode = fr ? fr : dnode_free;
                    276:     dict->context = context;
                    277: }
                    278: 
                    279: /*
                    280:  * Free a dynamically allocated dictionary object. Removing the nodes
                    281:  * from the tree before deleting it is required.
                    282:  */
                    283: 
                    284: void dict_destroy(dict_t *dict)
                    285: {
                    286:     assert (dict_isempty(dict));
                    287:     free(dict);
                    288: }
                    289: 
                    290: /*
                    291:  * Free all the nodes in the dictionary by using the dictionary's
                    292:  * installed free routine. The dictionary is emptied.
                    293:  */
                    294: 
                    295: void dict_free_nodes(dict_t *dict)
                    296: {
                    297:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
                    298:     free_nodes(dict, root, nil);
                    299:     dict->nodecount = 0;
                    300:     dict->nilnode.left = &dict->nilnode;
                    301:     dict->nilnode.right = &dict->nilnode;
                    302: }
                    303: 
                    304: /*
                    305:  * Obsolescent function, equivalent to dict_free_nodes
                    306:  */
                    307: 
                    308: void dict_free(dict_t *dict)
                    309: {
                    310: #ifdef KAZLIB_OBSOLESCENT_DEBUG
                    311:     assert ("call to obsolescent function dict_free()" && 0);
                    312: #endif
                    313:     dict_free_nodes(dict);
                    314: }
                    315: 
                    316: /*
                    317:  * Initialize a user-supplied dictionary object.
                    318:  */
                    319: 
                    320: dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
                    321: {
                    322:     dict->compare = comp;
                    323:     dict->allocnode = dnode_alloc;
                    324:     dict->freenode = dnode_free;
                    325:     dict->context = NULL;
                    326:     dict->nodecount = 0;
                    327:     dict->maxcount = maxcount;
                    328:     dict->nilnode.left = &dict->nilnode;
                    329:     dict->nilnode.right = &dict->nilnode;
                    330:     dict->nilnode.parent = &dict->nilnode;
                    331:     dict->nilnode.color = dnode_black;
                    332:     dict->dupes = 0;
                    333:     return dict;
                    334: }
                    335: 
                    336: /* 
                    337:  * Initialize a dictionary in the likeness of another dictionary
                    338:  */
                    339: 
                    340: void dict_init_like(dict_t *dict, const dict_t *template)
                    341: {
                    342:     dict->compare = template->compare;
                    343:     dict->allocnode = template->allocnode;
                    344:     dict->freenode = template->freenode;
                    345:     dict->context = template->context;
                    346:     dict->nodecount = 0;
                    347:     dict->maxcount = template->maxcount;
                    348:     dict->nilnode.left = &dict->nilnode;
                    349:     dict->nilnode.right = &dict->nilnode;
                    350:     dict->nilnode.parent = &dict->nilnode;
                    351:     dict->nilnode.color = dnode_black;
                    352:     dict->dupes = template->dupes;
                    353: 
                    354:     assert (dict_similar(dict, template));
                    355: }
                    356: 
                    357: /*
                    358:  * Remove all nodes from the dictionary (without freeing them in any way).
                    359:  */
                    360: 
                    361: static void dict_clear(dict_t *dict)
                    362: {
                    363:     dict->nodecount = 0;
                    364:     dict->nilnode.left = &dict->nilnode;
                    365:     dict->nilnode.right = &dict->nilnode;
                    366:     dict->nilnode.parent = &dict->nilnode;
                    367:     assert (dict->nilnode.color == dnode_black);
                    368: }
                    369: 
                    370: 
                    371: /*
                    372:  * Verify the integrity of the dictionary structure.  This is provided for
                    373:  * debugging purposes, and should be placed in assert statements.   Just because
                    374:  * this function succeeds doesn't mean that the tree is not corrupt. Certain
                    375:  * corruptions in the tree may simply cause undefined behavior.
                    376:  */ 
                    377: 
                    378: int dict_verify(dict_t *dict)
                    379: {
                    380:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
                    381: 
                    382:     /* check that the sentinel node and root node are black */
                    383:     if (root->color != dnode_black)
                    384:        return 0;
                    385:     if (nil->color != dnode_black)
                    386:        return 0;
                    387:     if (nil->right != nil)
                    388:        return 0;
                    389:     /* nil->left is the root node; check that its parent pointer is nil */
                    390:     if (nil->left->parent != nil)
                    391:        return 0;
                    392:     /* perform a weak test that the tree is a binary search tree */
                    393:     if (!verify_bintree(dict))
                    394:        return 0;
                    395:     /* verify that the tree is a red-black tree */
                    396:     if (!verify_redblack(nil, root))
                    397:        return 0;
                    398:     if (verify_node_count(nil, root) != dict_count(dict))
                    399:        return 0;
                    400:     return 1;
                    401: }
                    402: 
                    403: /*
                    404:  * Determine whether two dictionaries are similar: have the same comparison and
                    405:  * allocator functions, and same status as to whether duplicates are allowed.
                    406:  */
                    407: 
                    408: int dict_similar(const dict_t *left, const dict_t *right)
                    409: {
                    410:     if (left->compare != right->compare)
                    411:        return 0;
                    412: 
                    413:     if (left->allocnode != right->allocnode)
                    414:        return 0;
                    415: 
                    416:     if (left->freenode != right->freenode)
                    417:        return 0;
                    418: 
                    419:     if (left->context != right->context)
                    420:        return 0;
                    421: 
                    422:     if (left->dupes != right->dupes)
                    423:        return 0;
                    424: 
                    425:     return 1;
                    426: }
                    427: 
                    428: /*
                    429:  * Locate a node in the dictionary having the given key.
                    430:  * If the node is not found, a null a pointer is returned (rather than 
                    431:  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
                    432:  * located node is returned.
                    433:  */
                    434: 
                    435: dnode_t *dict_lookup(dict_t *dict, const void *key)
                    436: {
                    437:     dnode_t *root = dict_root(dict);
                    438:     dnode_t *nil = dict_nil(dict);
                    439:     dnode_t *saved;
                    440:     int result;
                    441: 
                    442:     /* simple binary search adapted for trees that contain duplicate keys */
                    443: 
                    444:     while (root != nil) {
                    445:        result = dict->compare(key, root->key);
                    446:        if (result < 0)
                    447:            root = root->left;
                    448:        else if (result > 0)
                    449:            root = root->right;
                    450:        else {
                    451:            if (!dict->dupes) { /* no duplicates, return match          */
                    452:                return root;
                    453:            } else {            /* could be dupes, find leftmost one    */
                    454:                do {
                    455:                    saved = root;
                    456:                    root = root->left;
                    457:                    while (root != nil && dict->compare(key, root->key))
                    458:                        root = root->right;
                    459:                } while (root != nil);
                    460:                return saved;
                    461:            }
                    462:        }
                    463:     }
                    464: 
                    465:     return NULL;
                    466: }
                    467: 
                    468: /*
                    469:  * Look for the node corresponding to the lowest key that is equal to or
                    470:  * greater than the given key.  If there is no such node, return null.
                    471:  */
                    472: 
                    473: dnode_t *dict_lower_bound(dict_t *dict, const void *key)
                    474: {
                    475:     dnode_t *root = dict_root(dict);
                    476:     dnode_t *nil = dict_nil(dict);
                    477:     dnode_t *tentative = 0;
                    478: 
                    479:     while (root != nil) {
                    480:        int result = dict->compare(key, root->key);
                    481: 
                    482:        if (result > 0) {
                    483:            root = root->right;
                    484:        } else if (result < 0) {
                    485:            tentative = root;
                    486:            root = root->left;
                    487:        } else {
                    488:            if (!dict->dupes) {
                    489:                return root;
                    490:            } else {
                    491:                tentative = root;
                    492:                root = root->left;
                    493:            }
                    494:        } 
                    495:     }
                    496:     
                    497:     return tentative;
                    498: }
                    499: 
                    500: /*
                    501:  * Look for the node corresponding to the greatest key that is equal to or
                    502:  * lower than the given key.  If there is no such node, return null.
                    503:  */
                    504: 
                    505: dnode_t *dict_upper_bound(dict_t *dict, const void *key)
                    506: {
                    507:     dnode_t *root = dict_root(dict);
                    508:     dnode_t *nil = dict_nil(dict);
                    509:     dnode_t *tentative = 0;
                    510: 
                    511:     while (root != nil) {
                    512:        int result = dict->compare(key, root->key);
                    513: 
                    514:        if (result < 0) {
                    515:            root = root->left;
                    516:        } else if (result > 0) {
                    517:            tentative = root;
                    518:            root = root->right;
                    519:        } else {
                    520:            if (!dict->dupes) {
                    521:                return root;
                    522:            } else {
                    523:                tentative = root;
                    524:                root = root->right;
                    525:            }
                    526:        } 
                    527:     }
                    528:     
                    529:     return tentative;
                    530: }
                    531: 
                    532: /*
                    533:  * Insert a node into the dictionary. The node should have been
                    534:  * initialized with a data field. All other fields are ignored.
                    535:  * The behavior is undefined if the user attempts to insert into
                    536:  * a dictionary that is already full (for which the dict_isfull()
                    537:  * function returns true).
                    538:  */
                    539: 
                    540: void dict_insert(dict_t *dict, dnode_t *node, const void *key)
                    541: {
                    542:     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
                    543:     dnode_t *parent = nil, *uncle, *grandpa;
                    544:     int result = -1;
                    545: 
                    546:     node->key = key;
                    547: 
                    548:     assert (!dict_isfull(dict));
                    549:     assert (!dict_contains(dict, node));
                    550:     assert (!dnode_is_in_a_dict(node));
                    551: 
                    552:     /* basic binary tree insert */
                    553: 
                    554:     while (where != nil) {
                    555:        parent = where;
                    556:        result = dict->compare(key, where->key);
                    557:        /* trap attempts at duplicate key insertion unless it's explicitly allowed */
                    558:        assert (dict->dupes || result != 0);
                    559:        if (result < 0)
                    560:            where = where->left;
                    561:        else
                    562:            where = where->right;
                    563:     }
                    564: 
                    565:     assert (where == nil);
                    566: 
                    567:     if (result < 0)
                    568:        parent->left = node;
                    569:     else
                    570:        parent->right = node;
                    571: 
                    572:     node->parent = parent;
                    573:     node->left = nil;
                    574:     node->right = nil;
                    575: 
                    576:     dict->nodecount++;
                    577: 
                    578:     /* red black adjustments */
                    579: 
                    580:     node->color = dnode_red;
                    581: 
                    582:     while (parent->color == dnode_red) {
                    583:        grandpa = parent->parent;
                    584:        if (parent == grandpa->left) {
                    585:            uncle = grandpa->right;
                    586:            if (uncle->color == dnode_red) {    /* red parent, red uncle */
                    587:                parent->color = dnode_black;
                    588:                uncle->color = dnode_black;
                    589:                grandpa->color = dnode_red;
                    590:                node = grandpa;
                    591:                parent = grandpa->parent;
                    592:            } else {                            /* red parent, black uncle */
                    593:                if (node == parent->right) {
                    594:                    rotate_left(parent);
                    595:                    parent = node;
                    596:                    assert (grandpa == parent->parent);
                    597:                    /* rotation between parent and child preserves grandpa */
                    598:                }
                    599:                parent->color = dnode_black;
                    600:                grandpa->color = dnode_red;
                    601:                rotate_right(grandpa);
                    602:                break;
                    603:            }
                    604:        } else {        /* symmetric cases: parent == parent->parent->right */
                    605:            uncle = grandpa->left;
                    606:            if (uncle->color == dnode_red) {
                    607:                parent->color = dnode_black;
                    608:                uncle->color = dnode_black;
                    609:                grandpa->color = dnode_red;
                    610:                node = grandpa;
                    611:                parent = grandpa->parent;
                    612:            } else {
                    613:                if (node == parent->left) {
                    614:                    rotate_right(parent);
                    615:                    parent = node;
                    616:                    assert (grandpa == parent->parent);
                    617:                }
                    618:                parent->color = dnode_black;
                    619:                grandpa->color = dnode_red;
                    620:                rotate_left(grandpa);
                    621:                break;
                    622:            }
                    623:        }
                    624:     }
                    625: 
                    626:     dict_root(dict)->color = dnode_black;
                    627: 
                    628:     assert (dict_verify(dict));
                    629: }
                    630: 
                    631: /*
                    632:  * Delete the given node from the dictionary. If the given node does not belong
                    633:  * to the given dictionary, undefined behavior results.  A pointer to the
                    634:  * deleted node is returned.
                    635:  */
                    636: 
                    637: dnode_t *dict_delete(dict_t *dict, dnode_t *delete)
                    638: {
                    639:     dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;
                    640: 
                    641:     /* basic deletion */
                    642: 
                    643:     assert (!dict_isempty(dict));
                    644:     assert (dict_contains(dict, delete));
                    645: 
                    646:     /*
                    647:      * If the node being deleted has two children, then we replace it with its
                    648:      * successor (i.e. the leftmost node in the right subtree.) By doing this,
                    649:      * we avoid the traditional algorithm under which the successor's key and
                    650:      * value *only* move to the deleted node and the successor is spliced out
                    651:      * from the tree. We cannot use this approach because the user may hold
                    652:      * pointers to the successor, or nodes may be inextricably tied to some
                    653:      * other structures by way of embedding, etc. So we must splice out the
                    654:      * node we are given, not some other node, and must not move contents from
                    655:      * one node to another behind the user's back.
                    656:      */
                    657: 
                    658:     if (delete->left != nil && delete->right != nil) {
                    659:        dnode_t *next = dict_next(dict, delete);
                    660:        dnode_t *nextparent = next->parent;
                    661:        dnode_color_t nextcolor = next->color;
                    662: 
                    663:        assert (next != nil);
                    664:        assert (next->parent != nil);
                    665:        assert (next->left == nil);
                    666: 
                    667:        /*
                    668:         * First, splice out the successor from the tree completely, by
                    669:         * moving up its right child into its place.
                    670:         */
                    671: 
                    672:        child = next->right;
                    673:        child->parent = nextparent;
                    674: 
                    675:        if (nextparent->left == next) {
                    676:            nextparent->left = child;
                    677:        } else {
                    678:            assert (nextparent->right == next);
                    679:            nextparent->right = child;
                    680:        }
                    681: 
                    682:        /*
                    683:         * Now that the successor has been extricated from the tree, install it
                    684:         * in place of the node that we want deleted.
                    685:         */
                    686: 
                    687:        next->parent = delparent;
                    688:        next->left = delete->left;
                    689:        next->right = delete->right;
                    690:        next->left->parent = next;
                    691:        next->right->parent = next;
                    692:        next->color = delete->color;
                    693:        delete->color = nextcolor;
                    694: 
                    695:        if (delparent->left == delete) {
                    696:            delparent->left = next;
                    697:        } else {
                    698:            assert (delparent->right == delete);
                    699:            delparent->right = next;
                    700:        }
                    701: 
                    702:     } else {
                    703:        assert (delete != nil);
                    704:        assert (delete->left == nil || delete->right == nil);
                    705: 
                    706:        child = (delete->left != nil) ? delete->left : delete->right;
                    707: 
                    708:        child->parent = delparent = delete->parent;         
                    709: 
                    710:        if (delete == delparent->left) {
                    711:            delparent->left = child;    
                    712:        } else {
                    713:            assert (delete == delparent->right);
                    714:            delparent->right = child;
                    715:        }
                    716:     }
                    717: 
                    718:     delete->parent = NULL;
                    719:     delete->right = NULL;
                    720:     delete->left = NULL;
                    721: 
                    722:     dict->nodecount--;
                    723: 
                    724:     assert (verify_bintree(dict));
                    725: 
                    726:     /* red-black adjustments */
                    727: 
                    728:     if (delete->color == dnode_black) {
                    729:        dnode_t *parent, *sister;
                    730: 
                    731:        dict_root(dict)->color = dnode_red;
                    732: 
                    733:        while (child->color == dnode_black) {
                    734:            parent = child->parent;
                    735:            if (child == parent->left) {
                    736:                sister = parent->right;
                    737:                assert (sister != nil);
                    738:                if (sister->color == dnode_red) {
                    739:                    sister->color = dnode_black;
                    740:                    parent->color = dnode_red;
                    741:                    rotate_left(parent);
                    742:                    sister = parent->right;
                    743:                    assert (sister != nil);
                    744:                }
                    745:                if (sister->left->color == dnode_black
                    746:                        && sister->right->color == dnode_black) {
                    747:                    sister->color = dnode_red;
                    748:                    child = parent;
                    749:                } else {
                    750:                    if (sister->right->color == dnode_black) {
                    751:                        assert (sister->left->color == dnode_red);
                    752:                        sister->left->color = dnode_black;
                    753:                        sister->color = dnode_red;
                    754:                        rotate_right(sister);
                    755:                        sister = parent->right;
                    756:                        assert (sister != nil);
                    757:                    }
                    758:                    sister->color = parent->color;
                    759:                    sister->right->color = dnode_black;
                    760:                    parent->color = dnode_black;
                    761:                    rotate_left(parent);
                    762:                    break;
                    763:                }
                    764:            } else {    /* symmetric case: child == child->parent->right */
                    765:                assert (child == parent->right);
                    766:                sister = parent->left;
                    767:                assert (sister != nil);
                    768:                if (sister->color == dnode_red) {
                    769:                    sister->color = dnode_black;
                    770:                    parent->color = dnode_red;
                    771:                    rotate_right(parent);
                    772:                    sister = parent->left;
                    773:                    assert (sister != nil);
                    774:                }
                    775:                if (sister->right->color == dnode_black
                    776:                        && sister->left->color == dnode_black) {
                    777:                    sister->color = dnode_red;
                    778:                    child = parent;
                    779:                } else {
                    780:                    if (sister->left->color == dnode_black) {
                    781:                        assert (sister->right->color == dnode_red);
                    782:                        sister->right->color = dnode_black;
                    783:                        sister->color = dnode_red;
                    784:                        rotate_left(sister);
                    785:                        sister = parent->left;
                    786:                        assert (sister != nil);
                    787:                    }
                    788:                    sister->color = parent->color;
                    789:                    sister->left->color = dnode_black;
                    790:                    parent->color = dnode_black;
                    791:                    rotate_right(parent);
                    792:                    break;
                    793:                }
                    794:            }
                    795:        }
                    796: 
                    797:        child->color = dnode_black;
                    798:        dict_root(dict)->color = dnode_black;
                    799:     }
                    800: 
                    801:     assert (dict_verify(dict));
                    802: 
                    803:     return delete;
                    804: }
                    805: 
                    806: /*
                    807:  * Allocate a node using the dictionary's allocator routine, give it
                    808:  * the data item.
                    809:  */
                    810: 
                    811: int dict_alloc_insert(dict_t *dict, const void *key, void *data)
                    812: {
                    813:     dnode_t *node = dict->allocnode(dict->context);
                    814: 
                    815:     if (node) {
                    816:        dnode_init(node, data);
                    817:        dict_insert(dict, node, key);
                    818:        return 1;
                    819:     }
                    820:     return 0;
                    821: }
                    822: 
                    823: void dict_delete_free(dict_t *dict, dnode_t *node)
                    824: {
                    825:     dict_delete(dict, node);
                    826:     dict->freenode(node, dict->context);
                    827: }
                    828: 
                    829: /*
                    830:  * Return the node with the lowest (leftmost) key. If the dictionary is empty
                    831:  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
                    832:  */
                    833: 
                    834: dnode_t *dict_first(dict_t *dict)
                    835: {
                    836:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
                    837: 
                    838:     if (root != nil)
                    839:        while ((left = root->left) != nil)
                    840:            root = left;
                    841: 
                    842:     return (root == nil) ? NULL : root;
                    843: }
                    844: 
                    845: /*
                    846:  * Return the node with the highest (rightmost) key. If the dictionary is empty
                    847:  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
                    848:  */
                    849: 
                    850: dnode_t *dict_last(dict_t *dict)
                    851: {
                    852:     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;
                    853: 
                    854:     if (root != nil)
                    855:        while ((right = root->right) != nil)
                    856:            root = right;
                    857: 
                    858:     return (root == nil) ? NULL : root;
                    859: }
                    860: 
                    861: /*
                    862:  * Return the given node's successor node---the node which has the
                    863:  * next key in the the left to right ordering. If the node has
                    864:  * no successor, a null pointer is returned rather than a pointer to
                    865:  * the nil node.
                    866:  */
                    867: 
                    868: dnode_t *dict_next(dict_t *dict, dnode_t *curr)
                    869: {
                    870:     dnode_t *nil = dict_nil(dict), *parent, *left;
                    871: 
                    872:     if (curr->right != nil) {
                    873:        curr = curr->right;
                    874:        while ((left = curr->left) != nil)
                    875:            curr = left;
                    876:        return curr;
                    877:     }
                    878: 
                    879:     parent = curr->parent;
                    880: 
                    881:     while (parent != nil && curr == parent->right) {
                    882:        curr = parent;
                    883:        parent = curr->parent;
                    884:     }
                    885: 
                    886:     return (parent == nil) ? NULL : parent;
                    887: }
                    888: 
                    889: /*
                    890:  * Return the given node's predecessor, in the key order.
                    891:  * The nil sentinel node is returned if there is no predecessor.
                    892:  */
                    893: 
                    894: dnode_t *dict_prev(dict_t *dict, dnode_t *curr)
                    895: {
                    896:     dnode_t *nil = dict_nil(dict), *parent, *right;
                    897: 
                    898:     if (curr->left != nil) {
                    899:        curr = curr->left;
                    900:        while ((right = curr->right) != nil)
                    901:            curr = right;
                    902:        return curr;
                    903:     }
                    904: 
                    905:     parent = curr->parent;
                    906: 
                    907:     while (parent != nil && curr == parent->left) {
                    908:        curr = parent;
                    909:        parent = curr->parent;
                    910:     }
                    911: 
                    912:     return (parent == nil) ? NULL : parent;
                    913: }
                    914: 
                    915: void dict_allow_dupes(dict_t *dict)
                    916: {
                    917:     dict->dupes = 1;
                    918: }
                    919: 
                    920: #undef dict_count
                    921: #undef dict_isempty
                    922: #undef dict_isfull
                    923: #undef dnode_get
                    924: #undef dnode_put
                    925: #undef dnode_getkey
                    926: 
                    927: dictcount_t dict_count(dict_t *dict)
                    928: {
                    929:     return dict->nodecount;
                    930: }
                    931: 
                    932: int dict_isempty(dict_t *dict)
                    933: {
                    934:     return dict->nodecount == 0;
                    935: }
                    936: 
                    937: int dict_isfull(dict_t *dict)
                    938: {
                    939:     return dict->nodecount == dict->maxcount;
                    940: }
                    941: 
                    942: int dict_contains(dict_t *dict, dnode_t *node)
                    943: {
                    944:     return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);
                    945: }
                    946: 
                    947: static dnode_t *dnode_alloc(void *context)
                    948: {
                    949:     return malloc(sizeof *dnode_alloc(NULL));
                    950: }
                    951: 
                    952: static void dnode_free(dnode_t *node, void *context)
                    953: {
                    954:     free(node);
                    955: }
                    956: 
                    957: dnode_t *dnode_create(void *data)
                    958: {
                    959:     dnode_t *new = malloc(sizeof *new);
                    960:     if (new) {
                    961:        new->data = data;
                    962:        new->parent = NULL;
                    963:        new->left = NULL;
                    964:        new->right = NULL;
                    965:     }
                    966:     return new;
                    967: }
                    968: 
                    969: dnode_t *dnode_init(dnode_t *dnode, void *data)
                    970: {
                    971:     dnode->data = data;
                    972:     dnode->parent = NULL;
                    973:     dnode->left = NULL;
                    974:     dnode->right = NULL;
                    975:     return dnode;
                    976: }
                    977: 
                    978: void dnode_destroy(dnode_t *dnode)
                    979: {
                    980:     assert (!dnode_is_in_a_dict(dnode));
                    981:     free(dnode);
                    982: }
                    983: 
                    984: void *dnode_get(dnode_t *dnode)
                    985: {
                    986:     return dnode->data;
                    987: }
                    988: 
                    989: const void *dnode_getkey(dnode_t *dnode)
                    990: {
                    991:     return dnode->key;
                    992: }
                    993: 
                    994: void dnode_put(dnode_t *dnode, void *data)
                    995: {
                    996:     dnode->data = data;
                    997: }
                    998: 
                    999: int dnode_is_in_a_dict(dnode_t *dnode)
                   1000: {
                   1001:     return (dnode->parent && dnode->left && dnode->right);
                   1002: }
                   1003: 
                   1004: void dict_process(dict_t *dict, void *context, dnode_process_t function)
                   1005: {
                   1006:     dnode_t *node = dict_first(dict), *next;
                   1007: 
                   1008:     while (node != NULL) {
                   1009:        /* check for callback function deleting */
                   1010:        /* the next node from under us          */
                   1011:        assert (dict_contains(dict, node));
                   1012:        next = dict_next(dict, node);
                   1013:        function(dict, node, context);
                   1014:        node = next;
                   1015:     }
                   1016: }
                   1017: 
                   1018: static void load_begin_internal(dict_load_t *load, dict_t *dict)
                   1019: {
                   1020:     load->dictptr = dict;
                   1021:     load->nilnode.left = &load->nilnode;
                   1022:     load->nilnode.right = &load->nilnode;
                   1023: }
                   1024: 
                   1025: void dict_load_begin(dict_load_t *load, dict_t *dict)
                   1026: {
                   1027:     assert (dict_isempty(dict));
                   1028:     load_begin_internal(load, dict);
                   1029: }
                   1030: 
                   1031: void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key)
                   1032: {
                   1033:     dict_t *dict = load->dictptr;
                   1034:     dnode_t *nil = &load->nilnode;
                   1035:    
                   1036:     assert (!dnode_is_in_a_dict(newnode));
                   1037:     assert (dict->nodecount < dict->maxcount);
                   1038: 
                   1039:     #ifndef NDEBUG
                   1040:     if (dict->nodecount > 0) {
                   1041:        if (dict->dupes)
                   1042:            assert (dict->compare(nil->left->key, key) <= 0);
                   1043:        else
                   1044:            assert (dict->compare(nil->left->key, key) < 0);
                   1045:     }
                   1046:     #endif
                   1047: 
                   1048:     newnode->key = key;
                   1049:     nil->right->left = newnode;
                   1050:     nil->right = newnode;
                   1051:     newnode->left = nil;
                   1052:     dict->nodecount++;
                   1053: }
                   1054: 
                   1055: void dict_load_end(dict_load_t *load)
                   1056: {
                   1057:     dict_t *dict = load->dictptr;
                   1058:     dnode_t *tree[DICT_DEPTH_MAX] = { 0 };
                   1059:     dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next;
                   1060:     dnode_t *complete = 0;
                   1061:     dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount;
                   1062:     dictcount_t botrowcount;
                   1063:     unsigned baselevel = 0, level = 0, i;
                   1064: 
                   1065:     assert (dnode_red == 0 && dnode_black == 1);
                   1066: 
                   1067:     while (fullcount >= nodecount && fullcount)
                   1068:        fullcount >>= 1;
                   1069: 
                   1070:     botrowcount = nodecount - fullcount;
                   1071: 
                   1072:     for (curr = loadnil->left; curr != loadnil; curr = next) {
                   1073:        next = curr->left;
                   1074: 
                   1075:        if (complete == NULL && botrowcount-- == 0) {
                   1076:            assert (baselevel == 0);
                   1077:            assert (level == 0);
                   1078:            baselevel = level = 1;
                   1079:            complete = tree[0];
                   1080: 
                   1081:            if (complete != 0) {
                   1082:                tree[0] = 0;
                   1083:                complete->right = dictnil;
                   1084:                while (tree[level] != 0) {
                   1085:                    tree[level]->right = complete;
                   1086:                    complete->parent = tree[level];
                   1087:                    complete = tree[level];
                   1088:                    tree[level++] = 0;
                   1089:                }
                   1090:            }
                   1091:        }
                   1092: 
                   1093:        if (complete == NULL) {
                   1094:            curr->left = dictnil;
                   1095:            curr->right = dictnil;
                   1096:            curr->color = level % 2;
                   1097:            complete = curr;
                   1098: 
                   1099:            assert (level == baselevel);
                   1100:            while (tree[level] != 0) {
                   1101:                tree[level]->right = complete;
                   1102:                complete->parent = tree[level];
                   1103:                complete = tree[level];
                   1104:                tree[level++] = 0;
                   1105:            }
                   1106:        } else {
                   1107:            curr->left = complete;
                   1108:            curr->color = (level + 1) % 2;
                   1109:            complete->parent = curr;
                   1110:            tree[level] = curr;
                   1111:            complete = 0;
                   1112:            level = baselevel;
                   1113:        }
                   1114:     }
                   1115: 
                   1116:     if (complete == NULL)
                   1117:        complete = dictnil;
                   1118: 
                   1119:     for (i = 0; i < DICT_DEPTH_MAX; i++) {
                   1120:        if (tree[i] != 0) {
                   1121:            tree[i]->right = complete;
                   1122:            complete->parent = tree[i];
                   1123:            complete = tree[i];
                   1124:        }
                   1125:     }
                   1126: 
                   1127:     dictnil->color = dnode_black;
                   1128:     dictnil->right = dictnil;
                   1129:     complete->parent = dictnil;
                   1130:     complete->color = dnode_black;
                   1131:     dict_root(dict) = complete;
                   1132: 
                   1133:     assert (dict_verify(dict));
                   1134: }
                   1135: 
                   1136: void dict_merge(dict_t *dest, dict_t *source)
                   1137: {
                   1138:     dict_load_t load;
                   1139:     dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source);
                   1140: 
                   1141:     assert (dict_similar(dest, source));       
                   1142: 
                   1143:     if (source == dest)
                   1144:        return;
                   1145: 
                   1146:     dest->nodecount = 0;
                   1147:     load_begin_internal(&load, dest);
                   1148: 
                   1149:     for (;;) {
                   1150:        if (leftnode != NULL && rightnode != NULL) {
                   1151:            if (dest->compare(leftnode->key, rightnode->key) < 0)
                   1152:                goto copyleft;
                   1153:            else
                   1154:                goto copyright;
                   1155:        } else if (leftnode != NULL) {
                   1156:            goto copyleft;
                   1157:        } else if (rightnode != NULL) {
                   1158:            goto copyright;
                   1159:        } else {
                   1160:            assert (leftnode == NULL && rightnode == NULL);
                   1161:            break;
                   1162:        }
                   1163: 
                   1164:     copyleft:
                   1165:        {
                   1166:            dnode_t *next = dict_next(dest, leftnode);
                   1167:            #ifndef NDEBUG
                   1168:            leftnode->left = NULL;      /* suppress assertion in dict_load_next */
                   1169:            #endif
                   1170:            dict_load_next(&load, leftnode, leftnode->key);
                   1171:            leftnode = next;
                   1172:            continue;
                   1173:        }
                   1174:        
                   1175:     copyright:
                   1176:        {
                   1177:            dnode_t *next = dict_next(source, rightnode);
                   1178:            #ifndef NDEBUG
                   1179:            rightnode->left = NULL;
                   1180:            #endif
                   1181:            dict_load_next(&load, rightnode, rightnode->key);
                   1182:            rightnode = next;
                   1183:            continue;
                   1184:        }
                   1185:     }
                   1186: 
                   1187:     dict_clear(source);
                   1188:     dict_load_end(&load);
                   1189: }
                   1190: 
                   1191: #ifdef KAZLIB_TEST_MAIN
                   1192: 
                   1193: #include <stdio.h>
                   1194: #include <string.h>
                   1195: #include <ctype.h>
                   1196: #include <stdarg.h>
                   1197: 
                   1198: typedef char input_t[256];
                   1199: 
                   1200: static int tokenize(char *string, ...)
                   1201: {
                   1202:     char **tokptr; 
                   1203:     va_list arglist;
                   1204:     int tokcount = 0;
                   1205: 
                   1206:     va_start(arglist, string);
                   1207:     tokptr = va_arg(arglist, char **);
                   1208:     while (tokptr) {
                   1209:        while (*string && isspace((unsigned char) *string))
                   1210:            string++;
                   1211:        if (!*string)
                   1212:            break;
                   1213:        *tokptr = string;
                   1214:        while (*string && !isspace((unsigned char) *string))
                   1215:            string++;
                   1216:        tokptr = va_arg(arglist, char **);
                   1217:        tokcount++;
                   1218:        if (!*string)
                   1219:            break;
                   1220:        *string++ = 0;
                   1221:     }
                   1222:     va_end(arglist);
                   1223: 
                   1224:     return tokcount;
                   1225: }
                   1226: 
                   1227: static int comparef(const void *key1, const void *key2)
                   1228: {
                   1229:     return strcmp(key1, key2);
                   1230: }
                   1231: 
                   1232: static char *dupstring(char *str)
                   1233: {
                   1234:     int sz = strlen(str) + 1;
                   1235:     char *new = malloc(sz);
                   1236:     if (new)
                   1237:        memcpy(new, str, sz);
                   1238:     return new;
                   1239: }
                   1240: 
                   1241: static dnode_t *new_node(void *c)
                   1242: {
                   1243:     static dnode_t few[5];
                   1244:     static int count;
                   1245: 
                   1246:     if (count < 5)
                   1247:        return few + count++;
                   1248: 
                   1249:     return NULL;
                   1250: }
                   1251: 
                   1252: static void del_node(dnode_t *n, void *c)
                   1253: {
                   1254: }
                   1255: 
                   1256: static int prompt = 0;
                   1257: 
                   1258: static void construct(dict_t *d)
                   1259: {
                   1260:     input_t in;
                   1261:     int done = 0;
                   1262:     dict_load_t dl;
                   1263:     dnode_t *dn;
                   1264:     char *tok1, *tok2, *val;
                   1265:     const char *key;
                   1266:     char *help = 
                   1267:        "p                      turn prompt on\n"
                   1268:        "q                      finish construction\n"
                   1269:        "a <key> <val>          add new entry\n";
                   1270: 
                   1271:     if (!dict_isempty(d))
                   1272:        puts("warning: dictionary not empty!");
                   1273: 
                   1274:     dict_load_begin(&dl, d);
                   1275: 
                   1276:     while (!done) {
                   1277:        if (prompt)
                   1278:            putchar('>');
                   1279:        fflush(stdout);
                   1280: 
                   1281:        if (!fgets(in, sizeof(input_t), stdin))
                   1282:            break;
                   1283: 
                   1284:        switch (in[0]) {
                   1285:            case '?':
                   1286:                puts(help);
                   1287:                break;
                   1288:            case 'p':
                   1289:                prompt = 1;
                   1290:                break;
                   1291:            case 'q':
                   1292:                done = 1;
                   1293:                break;
                   1294:            case 'a':
                   1295:                if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
                   1296:                    puts("what?");
                   1297:                    break;
                   1298:                }
                   1299:                key = dupstring(tok1);
                   1300:                val = dupstring(tok2);
                   1301:                dn = dnode_create(val);
                   1302: 
                   1303:                if (!key || !val || !dn) {
                   1304:                    puts("out of memory");
                   1305:                    free((void *) key);
                   1306:                    free(val);
                   1307:                    if (dn)
                   1308:                        dnode_destroy(dn);
                   1309:                }
                   1310: 
                   1311:                dict_load_next(&dl, dn, key);
                   1312:                break;
                   1313:            default:
                   1314:                putchar('?');
                   1315:                putchar('\n');
                   1316:                break;
                   1317:        }
                   1318:     }
                   1319: 
                   1320:     dict_load_end(&dl);
                   1321: }
                   1322: 
                   1323: int main(void)
                   1324: {
                   1325:     input_t in;
                   1326:     dict_t darray[10];
                   1327:     dict_t *d = &darray[0];
                   1328:     dnode_t *dn;
                   1329:     int i;
                   1330:     char *tok1, *tok2, *val;
                   1331:     const char *key;
                   1332: 
                   1333:     char *help =
                   1334:        "a <key> <val>          add value to dictionary\n"
                   1335:        "d <key>                delete value from dictionary\n"
                   1336:        "l <key>                lookup value in dictionary\n"
                   1337:        "( <key>                lookup lower bound\n"
                   1338:        ") <key>                lookup upper bound\n"
                   1339:        "# <num>                switch to alternate dictionary (0-9)\n"
                   1340:        "j <num> <num>          merge two dictionaries\n"
                   1341:        "f                      free the whole dictionary\n"
                   1342:        "k                      allow duplicate keys\n"
                   1343:        "c                      show number of entries\n"
                   1344:        "t                      dump whole dictionary in sort order\n"
                   1345:        "m                      make dictionary out of sorted items\n"
                   1346:        "p                      turn prompt on\n"
                   1347:        "s                      switch to non-functioning allocator\n"
                   1348:        "q                      quit";
                   1349: 
                   1350:     for (i = 0; i < sizeof darray / sizeof *darray; i++)
                   1351:        dict_init(&darray[i], DICTCOUNT_T_MAX, comparef);
                   1352: 
                   1353:     for (;;) {
                   1354:        if (prompt)
                   1355:            putchar('>');
                   1356:        fflush(stdout);
                   1357: 
                   1358:        if (!fgets(in, sizeof(input_t), stdin))
                   1359:            break;
                   1360: 
                   1361:        switch(in[0]) {
                   1362:            case '?':
                   1363:                puts(help);
                   1364:                break;
                   1365:            case 'a':
                   1366:                if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
                   1367:                    puts("what?");
                   1368:                    break;
                   1369:                }
                   1370:                key = dupstring(tok1);
                   1371:                val = dupstring(tok2);
                   1372: 
                   1373:                if (!key || !val) {
                   1374:                    puts("out of memory");
                   1375:                    free((void *) key);
                   1376:                    free(val);
                   1377:                }
                   1378: 
                   1379:                if (!dict_alloc_insert(d, key, val)) {
                   1380:                    puts("dict_alloc_insert failed");
                   1381:                    free((void *) key);
                   1382:                    free(val);
                   1383:                    break;
                   1384:                }
                   1385:                break;
                   1386:            case 'd':
                   1387:                if (tokenize(in+1, &tok1, (char **) 0) != 1) {
                   1388:                    puts("what?");
                   1389:                    break;
                   1390:                }
                   1391:                dn = dict_lookup(d, tok1);
                   1392:                if (!dn) {
                   1393:                    puts("dict_lookup failed");
                   1394:                    break;
                   1395:                }
                   1396:                val = dnode_get(dn);
                   1397:                key = dnode_getkey(dn);
                   1398:                dict_delete_free(d, dn);
                   1399: 
                   1400:                free(val);
                   1401:                free((void *) key);
                   1402:                break;
                   1403:            case 'f':
                   1404:                dict_free(d);
                   1405:                break;
                   1406:            case 'l':
                   1407:            case '(':
                   1408:            case ')':
                   1409:                if (tokenize(in+1, &tok1, (char **) 0) != 1) {
                   1410:                    puts("what?");
                   1411:                    break;
                   1412:                }
                   1413:                dn = 0;
                   1414:                switch (in[0]) {
                   1415:                case 'l':
                   1416:                    dn = dict_lookup(d, tok1);
                   1417:                    break;
                   1418:                case '(':
                   1419:                    dn = dict_lower_bound(d, tok1);
                   1420:                    break;
                   1421:                case ')':
                   1422:                    dn = dict_upper_bound(d, tok1);
                   1423:                    break;
                   1424:                }
                   1425:                if (!dn) {
                   1426:                    puts("lookup failed");
                   1427:                    break;
                   1428:                }
                   1429:                val = dnode_get(dn);
                   1430:                puts(val);
                   1431:                break;
                   1432:            case 'm':
                   1433:                construct(d);
                   1434:                break;
                   1435:            case 'k':
                   1436:                dict_allow_dupes(d);
                   1437:                break;
                   1438:            case 'c':
                   1439:                printf("%lu\n", (unsigned long) dict_count(d));
                   1440:                break;
                   1441:            case 't':
                   1442:                for (dn = dict_first(d); dn; dn = dict_next(d, dn)) {
                   1443:                    printf("%s\t%s\n", (char *) dnode_getkey(dn),
                   1444:                            (char *) dnode_get(dn));
                   1445:                }
                   1446:                break;
                   1447:            case 'q':
                   1448:                exit(0);
                   1449:                break;
                   1450:            case '\0':
                   1451:                break;
                   1452:            case 'p':
                   1453:                prompt = 1;
                   1454:                break;
                   1455:            case 's':
                   1456:                dict_set_allocator(d, new_node, del_node, NULL);
                   1457:                break;
                   1458:            case '#':
                   1459:                if (tokenize(in+1, &tok1, (char **) 0) != 1) {
                   1460:                    puts("what?");
                   1461:                    break;
                   1462:                } else {
                   1463:                    int dictnum = atoi(tok1);
                   1464:                    if (dictnum < 0 || dictnum > 9) {
                   1465:                        puts("invalid number");
                   1466:                        break;
                   1467:                    }
                   1468:                    d = &darray[dictnum];
                   1469:                }
                   1470:                break;
                   1471:            case 'j':
                   1472:                if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) {
                   1473:                    puts("what?");
                   1474:                    break;
                   1475:                } else {
                   1476:                    int dict1 = atoi(tok1), dict2 = atoi(tok2);
                   1477:                    if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) {
                   1478:                        puts("invalid number");
                   1479:                        break;
                   1480:                    }
                   1481:                    dict_merge(&darray[dict1], &darray[dict2]);
                   1482:                }
                   1483:                break;
                   1484:            default:
                   1485:                putchar('?');
                   1486:                putchar('\n');
                   1487:                break;
                   1488:        }
                   1489:     }
                   1490: 
                   1491:     return 0;
                   1492: }
                   1493: 
                   1494: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>