Add the given string to the contents of the keyword set. Return NULL for success, an error message otherwise. */
| 165 | /* Add the given string to the contents of the keyword set. Return NULL |
| 166 | for success, an error message otherwise. */ |
| 167 | const char * |
| 168 | kwsincr (kwset_t kws, char const *text, size_t len) |
| 169 | { |
| 170 | struct kwset *kwset; |
| 171 | register struct trie *trie; |
| 172 | register unsigned char label; |
| 173 | register struct tree *link; |
| 174 | register int depth; |
| 175 | struct tree *links[DEPTH_SIZE]; |
| 176 | enum { L, R } dirs[DEPTH_SIZE]; |
| 177 | struct tree *t, *r, *l, *rl, *lr; |
| 178 | |
| 179 | kwset = (struct kwset *) kws; |
| 180 | trie = kwset->trie; |
| 181 | text += len; |
| 182 | |
| 183 | /* Descend the trie (built of reversed keywords) character-by-character, |
| 184 | installing new nodes when necessary. */ |
| 185 | while (len--) |
| 186 | { |
| 187 | label = kwset->trans ? kwset->trans[U(*--text)] : *--text; |
| 188 | |
| 189 | /* Descend the tree of outgoing links for this trie node, |
| 190 | looking for the current character and keeping track |
| 191 | of the path followed. */ |
| 192 | link = trie->links; |
| 193 | links[0] = (struct tree *) &trie->links; |
| 194 | dirs[0] = L; |
| 195 | depth = 1; |
| 196 | |
| 197 | while (link && label != link->label) |
| 198 | { |
| 199 | links[depth] = link; |
| 200 | if (label < link->label) { |
| 201 | dirs[depth++] = L; |
| 202 | link = link->llink; |
| 203 | } else { |
| 204 | dirs[depth++] = R; |
| 205 | link = link->rlink; |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | /* The current character doesn't have an outgoing link at |
| 210 | this trie node, so build a new trie node and install |
| 211 | a link in the current trie node's tree. */ |
| 212 | if (!link) |
| 213 | { |
| 214 | link = (struct tree *) obstack_alloc(&kwset->obstack, |
| 215 | sizeof (struct tree)); |
| 216 | if (!link) |
| 217 | return "memory exhausted"; |
| 218 | link->llink = NULL; |
| 219 | link->rlink = NULL; |
| 220 | link->trie = (struct trie *) obstack_alloc(&kwset->obstack, |
| 221 | sizeof (struct trie)); |
| 222 | if (!link->trie) |
| 223 | { |
| 224 | obstack_free(&kwset->obstack, link); |
no test coverage detected