/** * rdictionary_lookup() -- recursive dictionary lookup * Walk binary tree, given by 'dn', looking for the string 's'. * For every node in the tree where 's' matches (including wildcards) * make a copy of that node, and append it to llist. */ static Dict_node * rdictionary_lookup(Dict_node *llist, Dict_node * dn, const char * s, int match_idiom) { /* see comment in dictionary_lookup below */ int m; Dict_node * dn_new; if (dn == NULL) return llist; m = dict_order_wild(s, dn->string); if (m >= 0) { llist = rdictionary_lookup(llist, dn->right, s, match_idiom); } if ((m == 0) && (match_idiom || !is_idiom_word(dn->string))) { dn_new = dict_node_new(); *dn_new = *dn; dn_new->right = llist; llist = dn_new; } if (m <= 0) { llist = rdictionary_lookup(llist, dn->left, s, match_idiom); } return llist; }
/* Resize and rehash dict. */ int dict_resize(struct dict *dict) { assert(dict != NULL && dict->idx <= dict_idx_max); size_t new_idx = dict->idx + 1; if (new_idx > dict_idx_max) return DICT_ENOMEM; size_t new_table_size = dict_table_sizes[new_idx]; struct dict_node **new_table = malloc( new_table_size * sizeof(struct dict_node *)); /* init table to all NULL */ size_t index; for (index = 0; index < new_table_size; index++) new_table[index] = NULL; size_t table_size = dict_table_sizes[dict->idx]; for (index = 0; index < table_size; index++) { struct dict_node *node = (dict->table)[index]; while (node != NULL) { struct dict_node *new_node = dict_node_new( node->key, node->len, node->val); if (new_node == NULL) return DICT_ENOMEM; size_t new_index = dict_table_idx( new_idx, new_node->key, new_node->len); struct dict_node *cursor = new_table[new_index]; if (cursor == NULL) { /* set as head node */ new_table[new_index] = new_node; } else { while (cursor->next != NULL) cursor = cursor->next; /* set as last node */ cursor->next = new_node; } /* shift next */ struct dict_node *next = node->next; dict_node_free(node); node = next; } } free(dict->table); dict->table = new_table; dict->idx = new_idx; return DICT_OK; }
/* Set a key into dict. */ int dict_iset(struct dict *dict, char *key, size_t len, void *val) { assert(dict != NULL); if ((dict_table_sizes[dict->idx] * DICT_LOAD_LIMIT < dict->len + 1) && dict_resize(dict) != DICT_OK) return DICT_ENOMEM; size_t index = dict_table_idx(dict->idx, key, len); struct dict_node *node = (dict->table)[index]; /* try to find this key. */ while (node != NULL) { if (dict_key_equals(node->key, node->len, key, len)) { node->key = key; node->len = len; node->val = val; return DICT_OK; } node = node->next; } /* create node if not found */ struct dict_node *new_node = dict_node_new(key, len, val); if (new_node == NULL) return DICT_ENOMEM; /* rewind to list head */ node = (dict->table)[index]; if (node == NULL) { /* if list is empty, set as head node */ (dict->table)[index] = new_node; } else { /* else append as tail node */ while (node->next != NULL) node = node->next; node->next = new_node; } dict->len += 1; return DICT_OK; }
/** * read_entry() -- read one dictionary entry * Starting with the current token, parse one dictionary entry. * A single dictionary entry must have one and only one colon in it, * and is terminated by a semi-colon. * Add these words to the dictionary. */ static int read_entry(Dictionary dict) { Exp *n; int i; Dict_node *dn_new, *dnx, *dn = NULL; /* Reset multi-byte shift state every line. */ memset(&dict->mbss, 0, sizeof(dict->mbss)); while (!is_equal(dict, ':')) { if (dict->is_special) { dict_error(dict, "I expected a word but didn\'t get it."); return 0; } /* If it's a word-file name */ /* However, be careful to reject "/.v" which is the division symbol * used in equations (.v means verb-like) */ if ((dict->token[0] == '/') && (dict->token[1] != '.')) { dn = read_word_file(dict, dn, dict->token); if (dn == NULL) { err_ctxt ec; ec.sent = NULL; err_msg(&ec, Error, "Error opening word file %s\n", dict->token); return 0; } } else { dn_new = dict_node_new(); dn_new->left = dn; dn = dn_new; dn->file = NULL; dn->string = string_set_add(dict->token, dict->string_set); } /* Advance to next entry, unless error */ if (0 == link_advance(dict)) goto syntax_error; } /* pass the : */ if (!link_advance(dict)) { goto syntax_error; } n = expression(dict); if (n == NULL) { goto syntax_error; } if (!is_equal(dict, ';')) { dict_error(dict, "Expecting \";\" at the end of an entry."); goto syntax_error; } /* pass the ; */ if (!link_advance(dict)) { goto syntax_error; } /* At this point, dn points to a list of Dict_nodes connected by * their left pointers. These are to be inserted into the dictionary */ i = 0; for (dnx = dn; dnx != NULL; dnx = dnx->left) { dnx->exp = n; i++; } insert_list(dict, dn, i); return 1; syntax_error: free_lookup_list(dn); return 0; }