46 |
#define obstack_chunk_alloc malloc |
#define obstack_chunk_alloc malloc |
47 |
#define obstack_chunk_free free |
#define obstack_chunk_free free |
48 |
|
|
49 |
|
#define U(c) ((unsigned char) (c)) |
50 |
|
|
51 |
/* Balanced tree of edges and labels leaving a given trie node. */ |
/* Balanced tree of edges and labels leaving a given trie node. */ |
52 |
struct tree |
struct tree |
53 |
{ |
{ |
95 |
|
|
96 |
kwset = (struct kwset *) malloc(sizeof (struct kwset)); |
kwset = (struct kwset *) malloc(sizeof (struct kwset)); |
97 |
if (!kwset) |
if (!kwset) |
98 |
return 0; |
return NULL; |
99 |
|
|
100 |
obstack_init(&kwset->obstack); |
obstack_init(&kwset->obstack); |
101 |
kwset->words = 0; |
kwset->words = 0; |
104 |
if (!kwset->trie) |
if (!kwset->trie) |
105 |
{ |
{ |
106 |
kwsfree((kwset_t) kwset); |
kwsfree((kwset_t) kwset); |
107 |
return 0; |
return NULL; |
108 |
} |
} |
109 |
kwset->trie->accepting = 0; |
kwset->trie->accepting = 0; |
110 |
kwset->trie->links = 0; |
kwset->trie->links = NULL; |
111 |
kwset->trie->parent = 0; |
kwset->trie->parent = NULL; |
112 |
kwset->trie->next = 0; |
kwset->trie->next = NULL; |
113 |
kwset->trie->fail = 0; |
kwset->trie->fail = NULL; |
114 |
kwset->trie->depth = 0; |
kwset->trie->depth = 0; |
115 |
kwset->trie->shift = 0; |
kwset->trie->shift = 0; |
116 |
kwset->mind = INT_MAX; |
kwset->mind = INT_MAX; |
117 |
kwset->maxd = -1; |
kwset->maxd = -1; |
118 |
kwset->target = 0; |
kwset->target = NULL; |
119 |
kwset->trans = trans; |
kwset->trans = trans; |
120 |
|
|
121 |
return (kwset_t) kwset; |
return (kwset_t) kwset; |
143 |
installing new nodes when necessary. */ |
installing new nodes when necessary. */ |
144 |
while (len--) |
while (len--) |
145 |
{ |
{ |
146 |
label = kwset->trans ? kwset->trans[(unsigned char) *--text] : *--text; |
label = kwset->trans ? kwset->trans[U(*--text)] : *--text; |
147 |
|
|
148 |
/* Descend the tree of outgoing links for this trie node, |
/* Descend the tree of outgoing links for this trie node, |
149 |
looking for the current character and keeping track |
looking for the current character and keeping track |
171 |
sizeof (struct tree)); |
sizeof (struct tree)); |
172 |
if (!link) |
if (!link) |
173 |
return _("memory exhausted"); |
return _("memory exhausted"); |
174 |
link->llink = 0; |
link->llink = NULL; |
175 |
link->rlink = 0; |
link->rlink = NULL; |
176 |
link->trie = (struct trie *) obstack_alloc(&kwset->obstack, |
link->trie = (struct trie *) obstack_alloc(&kwset->obstack, |
177 |
sizeof (struct trie)); |
sizeof (struct trie)); |
178 |
if (!link->trie) |
if (!link->trie) |
179 |
return _("memory exhausted"); |
return _("memory exhausted"); |
180 |
link->trie->accepting = 0; |
link->trie->accepting = 0; |
181 |
link->trie->links = 0; |
link->trie->links = NULL; |
182 |
link->trie->parent = trie; |
link->trie->parent = trie; |
183 |
link->trie->next = 0; |
link->trie->next = NULL; |
184 |
link->trie->fail = 0; |
link->trie->fail = NULL; |
185 |
link->trie->depth = trie->depth + 1; |
link->trie->depth = trie->depth + 1; |
186 |
link->trie->shift = 0; |
link->trie->shift = 0; |
187 |
link->label = label; |
link->label = label; |
275 |
if (trie->depth > kwset->maxd) |
if (trie->depth > kwset->maxd) |
276 |
kwset->maxd = trie->depth; |
kwset->maxd = trie->depth; |
277 |
|
|
278 |
return 0; |
return NULL; |
279 |
} |
} |
280 |
|
|
281 |
/* Enqueue the trie nodes referenced from the given tree in the |
/* Enqueue the trie nodes referenced from the given tree in the |
397 |
|
|
398 |
/* Check if we can use the simple boyer-moore algorithm, instead |
/* Check if we can use the simple boyer-moore algorithm, instead |
399 |
of the hairy commentz-walter algorithm. */ |
of the hairy commentz-walter algorithm. */ |
400 |
if (kwset->words == 1 && kwset->trans == 0) |
if (kwset->words == 1 && kwset->trans == NULL) |
401 |
{ |
{ |
402 |
/* Looking for just one string. Extract it from the trie. */ |
/* Looking for just one string. Extract it from the trie. */ |
403 |
kwset->target = obstack_alloc(&kwset->obstack, kwset->mind); |
kwset->target = obstack_alloc(&kwset->obstack, kwset->mind); |
408 |
} |
} |
409 |
/* Build the Boyer Moore delta. Boy that's easy compared to CW. */ |
/* Build the Boyer Moore delta. Boy that's easy compared to CW. */ |
410 |
for (i = 0; i < kwset->mind; ++i) |
for (i = 0; i < kwset->mind; ++i) |
411 |
delta[(unsigned char) kwset->target[i]] = kwset->mind - (i + 1); |
delta[U(kwset->target[i])] = kwset->mind - (i + 1); |
412 |
kwset->mind2 = kwset->mind; |
kwset->mind2 = kwset->mind; |
413 |
/* Find the minimal delta2 shift that we might make after |
/* Find the minimal delta2 shift that we might make after |
414 |
a backwards match has failed. */ |
a backwards match has failed. */ |
466 |
/* Create a vector, indexed by character code, of the outgoing links |
/* Create a vector, indexed by character code, of the outgoing links |
467 |
from the root node. */ |
from the root node. */ |
468 |
for (i = 0; i < NCHAR; ++i) |
for (i = 0; i < NCHAR; ++i) |
469 |
next[i] = 0; |
next[i] = NULL; |
470 |
treenext(kwset->trie->links, next); |
treenext(kwset->trie->links, next); |
471 |
|
|
472 |
if ((trans = kwset->trans) != 0) |
if ((trans = kwset->trans) != NULL) |
473 |
for (i = 0; i < NCHAR; ++i) |
for (i = 0; i < NCHAR; ++i) |
474 |
kwset->next[i] = next[(unsigned char) trans[i]]; |
kwset->next[i] = next[U(trans[i])]; |
475 |
else |
else |
476 |
for (i = 0; i < NCHAR; ++i) |
for (i = 0; i < NCHAR; ++i) |
477 |
kwset->next[i] = next[i]; |
kwset->next[i] = next[i]; |
478 |
} |
} |
479 |
|
|
480 |
/* Fix things up for any translation table. */ |
/* Fix things up for any translation table. */ |
481 |
if ((trans = kwset->trans) != 0) |
if ((trans = kwset->trans) != NULL) |
482 |
for (i = 0; i < NCHAR; ++i) |
for (i = 0; i < NCHAR; ++i) |
483 |
kwset->delta[i] = delta[(unsigned char) trans[i]]; |
kwset->delta[i] = delta[U(trans[i])]; |
484 |
else |
else |
485 |
for (i = 0; i < NCHAR; ++i) |
for (i = 0; i < NCHAR; ++i) |
486 |
kwset->delta[i] = delta[i]; |
kwset->delta[i] = delta[i]; |
487 |
|
|
488 |
return 0; |
return NULL; |
489 |
} |
} |
490 |
|
|
|
#define U(C) ((unsigned char) (C)) |
|
|
|
|
491 |
/* Fast boyer-moore search. */ |
/* Fast boyer-moore search. */ |
492 |
static size_t |
static size_t |
493 |
bmexec (kwset_t kws, char const *text, size_t size) |
bmexec (kwset_t kws, char const *text, size_t size) |
604 |
lim = text + len; |
lim = text + len; |
605 |
end = text; |
end = text; |
606 |
if ((d = kwset->mind) != 0) |
if ((d = kwset->mind) != 0) |
607 |
mch = 0; |
mch = NULL; |
608 |
else |
else |
609 |
{ |
{ |
610 |
mch = text, accept = kwset->trie; |
mch = text, accept = kwset->trie; |
614 |
if (len >= 4 * kwset->mind) |
if (len >= 4 * kwset->mind) |
615 |
qlim = lim - 4 * kwset->mind; |
qlim = lim - 4 * kwset->mind; |
616 |
else |
else |
617 |
qlim = 0; |
qlim = NULL; |
618 |
|
|
619 |
while (lim - end >= d) |
while (lim - end >= d) |
620 |
{ |
{ |
624 |
while ((d = delta[c = *end]) && end < qlim) |
while ((d = delta[c = *end]) && end < qlim) |
625 |
{ |
{ |
626 |
end += d; |
end += d; |
627 |
end += delta[(unsigned char) *end]; |
end += delta[U(*end)]; |
628 |
end += delta[(unsigned char) *end]; |
end += delta[U(*end)]; |
629 |
} |
} |
630 |
++end; |
++end; |
631 |
} |
} |
643 |
d = trie->shift; |
d = trie->shift; |
644 |
while (beg > text) |
while (beg > text) |
645 |
{ |
{ |
646 |
c = trans ? trans[(unsigned char) *--beg] : *--beg; |
c = trans ? trans[U(*--beg)] : *--beg; |
647 |
tree = trie->links; |
tree = trie->links; |
648 |
while (tree && c != tree->label) |
while (tree && c != tree->label) |
649 |
if (c < tree->label) |
if (c < tree->label) |
694 |
d = trie->shift; |
d = trie->shift; |
695 |
while (beg > text) |
while (beg > text) |
696 |
{ |
{ |
697 |
c = trans ? trans[(unsigned char) *--beg] : *--beg; |
c = trans ? trans[U(*--beg)] : *--beg; |
698 |
tree = trie->links; |
tree = trie->links; |
699 |
while (tree && c != tree->label) |
while (tree && c != tree->label) |
700 |
if (c < tree->label) |
if (c < tree->label) |
744 |
struct kwsmatch *kwsmatch) |
struct kwsmatch *kwsmatch) |
745 |
{ |
{ |
746 |
struct kwset const *kwset = (struct kwset *) kws; |
struct kwset const *kwset = (struct kwset *) kws; |
747 |
if (kwset->words == 1 && kwset->trans == 0) |
if (kwset->words == 1 && kwset->trans == NULL) |
748 |
{ |
{ |
749 |
size_t ret = bmexec (kws, text, size); |
size_t ret = bmexec (kws, text, size); |
750 |
if (kwsmatch != 0 && ret != (size_t) -1) |
if (kwsmatch != NULL && ret != (size_t) -1) |
751 |
{ |
{ |
752 |
kwsmatch->index = 0; |
kwsmatch->index = 0; |
753 |
kwsmatch->offset[0] = ret; |
kwsmatch->offset[0] = ret; |
766 |
struct kwset *kwset; |
struct kwset *kwset; |
767 |
|
|
768 |
kwset = (struct kwset *) kws; |
kwset = (struct kwset *) kws; |
769 |
obstack_free(&kwset->obstack, 0); |
obstack_free(&kwset->obstack, NULL); |
770 |
free(kws); |
free(kws); |
771 |
} |
} |