2  * This file has been copied from commit e7ac713d^ in the GNU grep git
 
   3  * repository. A few small changes have been made to adapt the code to
 
   7 /* kwset.c - search for any of a set of keywords.
 
   8    Copyright 1989, 1998, 2000, 2005 Free Software Foundation, Inc.
 
  10    This program is free software; you can redistribute it and/or modify
 
  11    it under the terms of the GNU General Public License as published by
 
  12    the Free Software Foundation; either version 2, or (at your option)
 
  15    This program is distributed in the hope that it will be useful,
 
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  18    GNU General Public License for more details.
 
  20    You should have received a copy of the GNU General Public License
 
  21    along with this program; if not, see <http://www.gnu.org/licenses/>. */
 
  23 /* Written August 1989 by Mike Haertel.
 
  24    The author may be reached (Email) at the address mike@ai.mit.edu,
 
  25    or (US mail) as Mike Haertel c/o Free Software Foundation. */
 
  27 /* The algorithm implemented by these routines bears a startling resemblance
 
  28    to one discovered by Beate Commentz-Walter, although it is not identical.
 
  29    See "A String Matching Algorithm Fast on the Average," Technical Report,
 
  30    IBM-Germany, Scientific Center Heidelberg, Tiergartenstrasse 15, D-6900
 
  31    Heidelberg, Germany.  See also Aho, A.V., and M. Corasick, "Efficient
 
  32    String Matching:  An Aid to Bibliographic Search," CACM June 1975,
 
  33    Vol. 18, No. 6, which describes the failure function used below. */
 
  38 #include "compat/obstack.h"
 
  40 #define NCHAR (UCHAR_MAX + 1)
 
  41 /* adapter for `xmalloc()`, which takes `size_t`, not `long` */
 
  42 static void *obstack_chunk_alloc(long size)
 
  45                 BUG("Cannot allocate a negative amount: %ld", size);
 
  48 #define obstack_chunk_free free
 
  50 #define U(c) ((unsigned char) (c))
 
  52 /* Balanced tree of edges and labels leaving a given trie node. */
 
  55   struct tree *llink;           /* Left link; MUST be first field. */
 
  56   struct tree *rlink;           /* Right link (to larger labels). */
 
  57   struct trie *trie;            /* Trie node pointed to by this edge. */
 
  58   unsigned char label;          /* Label on this edge. */
 
  59   char balance;                 /* Difference in depths of subtrees. */
 
  62 /* Node of a trie representing a set of reversed keywords. */
 
  65   unsigned int accepting;       /* Word index of accepted word, or zero. */
 
  66   struct tree *links;           /* Tree of edges leaving this node. */
 
  67   struct trie *parent;          /* Parent of this node. */
 
  68   struct trie *next;            /* List of all trie nodes in level order. */
 
  69   struct trie *fail;            /* Aho-Corasick failure function. */
 
  70   int depth;                    /* Depth of this node from the root. */
 
  71   int shift;                    /* Shift function for search failures. */
 
  72   int maxshift;                 /* Max shift of self and descendants. */
 
  75 /* Structure returned opaquely to the caller, containing everything. */
 
  78   struct obstack obstack;       /* Obstack for node allocation. */
 
  79   int words;                    /* Number of words in the trie. */
 
  80   struct trie *trie;            /* The trie itself. */
 
  81   int mind;                     /* Minimum depth of an accepting node. */
 
  82   int maxd;                     /* Maximum depth of any node. */
 
  83   unsigned char delta[NCHAR];   /* Delta table for rapid search. */
 
  84   struct trie *next[NCHAR];     /* Table of children of the root. */
 
  85   char *target;                 /* Target string if there's only one. */
 
  86   int mind2;                    /* Used in Boyer-Moore search for one string. */
 
  87   unsigned char const *trans;  /* Character translation table. */
 
  90 /* Allocate and initialize a keyword set object, returning an opaque
 
  91    pointer to it.  Return NULL if memory is not available. */
 
  93 kwsalloc (unsigned char const *trans)
 
  97   kwset = (struct kwset *) xmalloc(sizeof (struct kwset));
 
  99   obstack_init(&kwset->obstack);
 
 102     = (struct trie *) obstack_alloc(&kwset->obstack, sizeof (struct trie));
 
 105       kwsfree((kwset_t) kwset);
 
 108   kwset->trie->accepting = 0;
 
 109   kwset->trie->links = NULL;
 
 110   kwset->trie->parent = NULL;
 
 111   kwset->trie->next = NULL;
 
 112   kwset->trie->fail = NULL;
 
 113   kwset->trie->depth = 0;
 
 114   kwset->trie->shift = 0;
 
 115   kwset->mind = INT_MAX;
 
 117   kwset->target = NULL;
 
 118   kwset->trans = trans;
 
 120   return (kwset_t) kwset;
 
 123 /* This upper bound is valid for CHAR_BIT >= 4 and
 
 124    exact for CHAR_BIT in { 4..11, 13, 15, 17, 19 }. */
 
 125 #define DEPTH_SIZE (CHAR_BIT + CHAR_BIT/2)
 
 127 /* Add the given string to the contents of the keyword set.  Return NULL
 
 128    for success, an error message otherwise. */
 
 130 kwsincr (kwset_t kws, char const *text, size_t len)
 
 133   register struct trie *trie;
 
 134   register unsigned char label;
 
 135   register struct tree *link;
 
 137   struct tree *links[DEPTH_SIZE];
 
 138   enum { L, R } dirs[DEPTH_SIZE];
 
 139   struct tree *t, *r, *l, *rl, *lr;
 
 141   kwset = (struct kwset *) kws;
 
 145   /* Descend the trie (built of reversed keywords) character-by-character,
 
 146      installing new nodes when necessary. */
 
 149       label = kwset->trans ? kwset->trans[U(*--text)] : *--text;
 
 151       /* Descend the tree of outgoing links for this trie node,
 
 152          looking for the current character and keeping track
 
 153          of the path followed. */
 
 155       links[0] = (struct tree *) &trie->links;
 
 159       while (link && label != link->label)
 
 162           if (label < link->label)
 
 163             dirs[depth++] = L, link = link->llink;
 
 165             dirs[depth++] = R, link = link->rlink;
 
 168       /* The current character doesn't have an outgoing link at
 
 169          this trie node, so build a new trie node and install
 
 170          a link in the current trie node's tree. */
 
 173           link = (struct tree *) obstack_alloc(&kwset->obstack,
 
 174                                                sizeof (struct tree));
 
 176             return "memory exhausted";
 
 179           link->trie = (struct trie *) obstack_alloc(&kwset->obstack,
 
 180                                                      sizeof (struct trie));
 
 183               obstack_free(&kwset->obstack, link);
 
 184               return "memory exhausted";
 
 186           link->trie->accepting = 0;
 
 187           link->trie->links = NULL;
 
 188           link->trie->parent = trie;
 
 189           link->trie->next = NULL;
 
 190           link->trie->fail = NULL;
 
 191           link->trie->depth = trie->depth + 1;
 
 192           link->trie->shift = 0;
 
 196           /* Install the new tree node in its parent. */
 
 197           if (dirs[--depth] == L)
 
 198             links[depth]->llink = link;
 
 200             links[depth]->rlink = link;
 
 202           /* Back up the tree fixing the balance flags. */
 
 203           while (depth && !links[depth]->balance)
 
 205               if (dirs[depth] == L)
 
 206                 --links[depth]->balance;
 
 208                 ++links[depth]->balance;
 
 212           /* Rebalance the tree by pointer rotations if necessary. */
 
 213           if (depth && ((dirs[depth] == L && --links[depth]->balance)
 
 214                         || (dirs[depth] == R && ++links[depth]->balance)))
 
 216               switch (links[depth]->balance)
 
 219                   switch (dirs[depth + 1])
 
 222                       r = links[depth], t = r->llink, rl = t->rlink;
 
 223                       t->rlink = r, r->llink = rl;
 
 224                       t->balance = r->balance = 0;
 
 227                       r = links[depth], l = r->llink, t = l->rlink;
 
 228                       rl = t->rlink, lr = t->llink;
 
 229                       t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl;
 
 230                       l->balance = t->balance != 1 ? 0 : -1;
 
 231                       r->balance = t->balance != (char) -1 ? 0 : 1;
 
 239                   switch (dirs[depth + 1])
 
 242                       l = links[depth], t = l->rlink, lr = t->llink;
 
 243                       t->llink = l, l->rlink = lr;
 
 244                       t->balance = l->balance = 0;
 
 247                       l = links[depth], r = l->rlink, t = r->llink;
 
 248                       lr = t->llink, rl = t->rlink;
 
 249                       t->llink = l, l->rlink = lr, t->rlink = r, r->llink = rl;
 
 250                       l->balance = t->balance != 1 ? 0 : -1;
 
 251                       r->balance = t->balance != (char) -1 ? 0 : 1;
 
 262               if (dirs[depth - 1] == L)
 
 263                 links[depth - 1]->llink = t;
 
 265                 links[depth - 1]->rlink = t;
 
 272   /* Mark the node we finally reached as accepting, encoding the
 
 273      index number of this word in the keyword set so far. */
 
 274   if (!trie->accepting)
 
 275     trie->accepting = 1 + 2 * kwset->words;
 
 278   /* Keep track of the longest and shortest string of the keyword set. */
 
 279   if (trie->depth < kwset->mind)
 
 280     kwset->mind = trie->depth;
 
 281   if (trie->depth > kwset->maxd)
 
 282     kwset->maxd = trie->depth;
 
 287 /* Enqueue the trie nodes referenced from the given tree in the
 
 290 enqueue (struct tree *tree, struct trie **last)
 
 294   enqueue(tree->llink, last);
 
 295   enqueue(tree->rlink, last);
 
 296   (*last) = (*last)->next = tree->trie;
 
 299 /* Compute the Aho-Corasick failure function for the trie nodes referenced
 
 300    from the given tree, given the failure function for their parent as
 
 301    well as a last resort failure node. */
 
 303 treefails (register struct tree const *tree, struct trie const *fail,
 
 304            struct trie *recourse)
 
 306   register struct tree *link;
 
 311   treefails(tree->llink, fail, recourse);
 
 312   treefails(tree->rlink, fail, recourse);
 
 314   /* Find, in the chain of fails going back to the root, the first
 
 315      node that has a descendant on the current label. */
 
 319       while (link && tree->label != link->label)
 
 320         if (tree->label < link->label)
 
 326           tree->trie->fail = link->trie;
 
 332   tree->trie->fail = recourse;
 
 335 /* Set delta entries for the links of the given tree such that
 
 336    the preexisting delta value is larger than the current depth. */
 
 338 treedelta (register struct tree const *tree,
 
 339            register unsigned int depth,
 
 340            unsigned char delta[])
 
 344   treedelta(tree->llink, depth, delta);
 
 345   treedelta(tree->rlink, depth, delta);
 
 346   if (depth < delta[tree->label])
 
 347     delta[tree->label] = depth;
 
 350 /* Return true if A has every label in B. */
 
 352 hasevery (register struct tree const *a, register struct tree const *b)
 
 356   if (!hasevery(a, b->llink))
 
 358   if (!hasevery(a, b->rlink))
 
 360   while (a && b->label != a->label)
 
 361     if (b->label < a->label)
 
 368 /* Compute a vector, indexed by character code, of the trie nodes
 
 369    referenced from the given tree. */
 
 371 treenext (struct tree const *tree, struct trie *next[])
 
 375   treenext(tree->llink, next);
 
 376   treenext(tree->rlink, next);
 
 377   next[tree->label] = tree->trie;
 
 380 /* Compute the shift for each trie node, as well as the delta
 
 381    table and next cache for the given keyword set. */
 
 383 kwsprep (kwset_t kws)
 
 385   register struct kwset *kwset;
 
 387   register struct trie *curr;
 
 388   register unsigned char const *trans;
 
 389   unsigned char delta[NCHAR];
 
 391   kwset = (struct kwset *) kws;
 
 393   /* Initial values for the delta table; will be changed later.  The
 
 394      delta entry for a given character is the smallest depth of any
 
 395      node at which an outgoing edge is labeled by that character. */
 
 396   memset(delta, kwset->mind < UCHAR_MAX ? kwset->mind : UCHAR_MAX, NCHAR);
 
 398   /* Check if we can use the simple boyer-moore algorithm, instead
 
 399      of the hairy commentz-walter algorithm. */
 
 400   if (kwset->words == 1 && kwset->trans == NULL)
 
 404       /* Looking for just one string.  Extract it from the trie. */
 
 405       kwset->target = obstack_alloc(&kwset->obstack, kwset->mind);
 
 407         return "memory exhausted";
 
 408       for (i = kwset->mind - 1, curr = kwset->trie; i >= 0; --i)
 
 410           kwset->target[i] = curr->links->label;
 
 411           curr = curr->links->trie;
 
 413       /* Build the Boyer Moore delta.  Boy that's easy compared to CW. */
 
 414       for (i = 0; i < kwset->mind; ++i)
 
 415         delta[U(kwset->target[i])] = kwset->mind - (i + 1);
 
 416       /* Find the minimal delta2 shift that we might make after
 
 417          a backwards match has failed. */
 
 418       c = kwset->target[kwset->mind - 1];
 
 419       for (i = kwset->mind - 2; i >= 0; --i)
 
 420         if (kwset->target[i] == c)
 
 422       kwset->mind2 = kwset->mind - (i + 1);
 
 426       register struct trie *fail;
 
 427       struct trie *last, *next[NCHAR];
 
 429       /* Traverse the nodes of the trie in level order, simultaneously
 
 430          computing the delta table, failure function, and shift function. */
 
 431       for (curr = last = kwset->trie; curr; curr = curr->next)
 
 433           /* Enqueue the immediate descendants in the level order queue. */
 
 434           enqueue(curr->links, &last);
 
 436           curr->shift = kwset->mind;
 
 437           curr->maxshift = kwset->mind;
 
 439           /* Update the delta table for the descendants of this node. */
 
 440           treedelta(curr->links, curr->depth, delta);
 
 442           /* Compute the failure function for the descendants of this node. */
 
 443           treefails(curr->links, curr->fail, kwset->trie);
 
 445           /* Update the shifts at each node in the current node's chain
 
 446              of fails back to the root. */
 
 447           for (fail = curr->fail; fail; fail = fail->fail)
 
 449               /* If the current node has some outgoing edge that the fail
 
 450                  doesn't, then the shift at the fail should be no larger
 
 451                  than the difference of their depths. */
 
 452               if (!hasevery(fail->links, curr->links))
 
 453                 if (curr->depth - fail->depth < fail->shift)
 
 454                   fail->shift = curr->depth - fail->depth;
 
 456               /* If the current node is accepting then the shift at the
 
 457                  fail and its descendants should be no larger than the
 
 458                  difference of their depths. */
 
 459               if (curr->accepting && fail->maxshift > curr->depth - fail->depth)
 
 460                 fail->maxshift = curr->depth - fail->depth;
 
 464       /* Traverse the trie in level order again, fixing up all nodes whose
 
 465          shift exceeds their inherited maxshift. */
 
 466       for (curr = kwset->trie->next; curr; curr = curr->next)
 
 468           if (curr->maxshift > curr->parent->maxshift)
 
 469             curr->maxshift = curr->parent->maxshift;
 
 470           if (curr->shift > curr->maxshift)
 
 471             curr->shift = curr->maxshift;
 
 474       /* Create a vector, indexed by character code, of the outgoing links
 
 475          from the root node. */
 
 476       for (i = 0; i < NCHAR; ++i)
 
 478       treenext(kwset->trie->links, next);
 
 480       if ((trans = kwset->trans) != NULL)
 
 481         for (i = 0; i < NCHAR; ++i)
 
 482           kwset->next[i] = next[U(trans[i])];
 
 484         COPY_ARRAY(kwset->next, next, NCHAR);
 
 487   /* Fix things up for any translation table. */
 
 488   if ((trans = kwset->trans) != NULL)
 
 489     for (i = 0; i < NCHAR; ++i)
 
 490       kwset->delta[i] = delta[U(trans[i])];
 
 492     memcpy(kwset->delta, delta, NCHAR);
 
 497 /* Fast boyer-moore search. */
 
 499 bmexec (kwset_t kws, char const *text, size_t size)
 
 501   struct kwset const *kwset;
 
 502   register unsigned char const *d1;
 
 503   register char const *ep, *sp, *tp;
 
 504   register int d, gc, i, len, md2;
 
 506   kwset = (struct kwset const *) kws;
 
 515       tp = memchr (text, kwset->target[0], size);
 
 516       return tp ? tp - text : -1;
 
 520   sp = kwset->target + len;
 
 525   /* Significance of 12: 1 (initial offset) + 10 (skip loop) + 1 (md2). */
 
 527     /* 11 is not a bug, the initial offset happens only once. */
 
 528     for (ep = text + size - 11 * len;;)
 
 532             d = d1[U(tp[-1])], tp += d;
 
 533             d = d1[U(tp[-1])], tp += d;
 
 536             d = d1[U(tp[-1])], tp += d;
 
 537             d = d1[U(tp[-1])], tp += d;
 
 538             d = d1[U(tp[-1])], tp += d;
 
 541             d = d1[U(tp[-1])], tp += d;
 
 542             d = d1[U(tp[-1])], tp += d;
 
 543             d = d1[U(tp[-1])], tp += d;
 
 546             d = d1[U(tp[-1])], tp += d;
 
 547             d = d1[U(tp[-1])], tp += d;
 
 553             for (i = 3; i <= len && U(tp[-i]) == U(sp[-i]); ++i)
 
 556               return tp - len - text;
 
 561   /* Now we have only a few characters left to search.  We
 
 562      carefully avoid ever producing an out-of-bounds pointer. */
 
 567       d = d1[U((tp += d)[-1])];
 
 572           for (i = 3; i <= len && U(tp[-i]) == U(sp[-i]); ++i)
 
 575             return tp - len - text;
 
 583 /* Hairy multiple string search. */
 
 585 cwexec (kwset_t kws, char const *text, size_t len, struct kwsmatch *kwsmatch)
 
 587   struct kwset const *kwset;
 
 588   struct trie * const *next;
 
 589   struct trie const *trie;
 
 590   struct trie const *accept;
 
 591   char const *beg, *lim, *mch, *lmch;
 
 592   register unsigned char c;
 
 593   register unsigned char const *delta;
 
 595   register char const *end, *qlim;
 
 596   register struct tree const *tree;
 
 597   register unsigned char const *trans;
 
 601   /* Initialize register copies and look for easy ways out. */
 
 602   kwset = (struct kwset *) kws;
 
 603   if (len < kwset->mind)
 
 606   delta = kwset->delta;
 
 607   trans = kwset->trans;
 
 610   if ((d = kwset->mind) != 0)
 
 614       mch = text, accept = kwset->trie;
 
 618   if (len >= 4 * kwset->mind)
 
 619     qlim = lim - 4 * kwset->mind;
 
 623   while (lim - end >= d)
 
 625       if (qlim && end <= qlim)
 
 628           while ((d = delta[c = *end]) && end < qlim)
 
 631               end += delta[U(*end)];
 
 632               end += delta[U(*end)];
 
 637         d = delta[c = (end += d)[-1]];
 
 650           c = trans ? trans[U(*--beg)] : *--beg;
 
 652           while (tree && c != tree->label)
 
 676   /* Given a known match, find the longest possible match anchored
 
 677      at or before its starting point.  This is nearly a verbatim
 
 678      copy of the preceding main search loops. */
 
 679   if (lim - mch > kwset->maxd)
 
 680     lim = mch + kwset->maxd;
 
 683   while (lim - end >= d)
 
 685       if ((d = delta[c = (end += d)[-1]]) != 0)
 
 688       if (!(trie = next[c]))
 
 693       if (trie->accepting && beg <= mch)
 
 701           c = trans ? trans[U(*--beg)] : *--beg;
 
 703           while (tree && c != tree->label)
 
 711               if (trie->accepting && beg <= mch)
 
 732       kwsmatch->index = accept->accepting / 2;
 
 733       kwsmatch->offset[0] = mch - text;
 
 734       kwsmatch->size[0] = accept->depth;
 
 739 /* Search through the given text for a match of any member of the
 
 740    given keyword set.  Return a pointer to the first character of
 
 741    the matching substring, or NULL if no match is found.  If FOUNDLEN
 
 742    is non-NULL store in the referenced location the length of the
 
 743    matching substring.  Similarly, if FOUNDIDX is non-NULL, store
 
 744    in the referenced location the index number of the particular
 
 747 kwsexec (kwset_t kws, char const *text, size_t size,
 
 748          struct kwsmatch *kwsmatch)
 
 750   struct kwset const *kwset = (struct kwset *) kws;
 
 751   if (kwset->words == 1 && kwset->trans == NULL)
 
 753       size_t ret = bmexec (kws, text, size);
 
 754       if (kwsmatch != NULL && ret != (size_t) -1)
 
 757           kwsmatch->offset[0] = ret;
 
 758           kwsmatch->size[0] = kwset->mind;
 
 763     return cwexec(kws, text, size, kwsmatch);
 
 766 /* Free the components of the given keyword set. */
 
 768 kwsfree (kwset_t kws)
 
 772   kwset = (struct kwset *) kws;
 
 773   obstack_free(&kwset->obstack, NULL);