Siddhesh Poyarekar 70cc4d3
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
Siddhesh Poyarekar 70cc4d3
index ecda08f..ec630fe 100644
Siddhesh Poyarekar 70cc4d3
--- a/string/strcoll_l.c
Siddhesh Poyarekar 70cc4d3
+++ b/string/strcoll_l.c
Siddhesh Poyarekar 70cc4d3
@@ -41,11 +41,434 @@
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
 #include "../locale/localeinfo.h"
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
+/* Track status while looking for sequences in a string.  */
Siddhesh Poyarekar 70cc4d3
+typedef struct
Siddhesh Poyarekar 70cc4d3
+{
Siddhesh Poyarekar 70cc4d3
+  int len;			/* Length of the current sequence.  */
Siddhesh Poyarekar 70cc4d3
+  int val;			/* Position of the sequence relative to the
Siddhesh Poyarekar 70cc4d3
+				   previous non-ignored sequence.  */
Siddhesh Poyarekar 70cc4d3
+  size_t idxnow;		/* Current index in sequences.  */
Siddhesh Poyarekar 70cc4d3
+  size_t idxmax;		/* Maximum index in sequences.  */
Siddhesh Poyarekar 70cc4d3
+  size_t idxcnt;		/* Current count of indeces.  */
Siddhesh Poyarekar 70cc4d3
+  size_t backw;			/* Current Backward sequence index.  */
Siddhesh Poyarekar 70cc4d3
+  size_t backw_stop;		/* Index where the backward sequences stop.  */
Siddhesh Poyarekar 70cc4d3
+  const USTRING_TYPE *us;	/* The string.  */
Siddhesh Poyarekar 70cc4d3
+  int32_t *idxarr;		/* Array to cache weight indeces.  */
Siddhesh Poyarekar 70cc4d3
+  unsigned char *rulearr;	/* Array to cache rules.  */
Siddhesh Poyarekar 70cc4d3
+  unsigned char rule;		/* Saved rule for the first sequence.  */
Siddhesh Poyarekar 70cc4d3
+  int32_t idx;			/* Index to weight of the current sequence.  */
Siddhesh Poyarekar 70cc4d3
+  int32_t save_idx;		/* Save looked up index of a forward
Siddhesh Poyarekar 70cc4d3
+				   sequence after the last backward
Siddhesh Poyarekar 70cc4d3
+				   sequence.  */
Siddhesh Poyarekar 70cc4d3
+  const USTRING_TYPE *back_us;	/* Beginning of the backward sequence.  */
Siddhesh Poyarekar 70cc4d3
+} coll_seq;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+/* Get next sequence.  The weight indeces are cached, so we don't need to
Siddhesh Poyarekar 70cc4d3
+   traverse the string.  */
Siddhesh Poyarekar 70cc4d3
+static void
Siddhesh Poyarekar 70cc4d3
+get_next_seq_cached (coll_seq *seq, int nrules, int pass,
Siddhesh Poyarekar 70cc4d3
+		     const unsigned char *rulesets,
Siddhesh Poyarekar 70cc4d3
+		     const USTRING_TYPE *weights)
Siddhesh Poyarekar 70cc4d3
+{
Siddhesh Poyarekar 70cc4d3
+  int val = seq->val = 0;
Siddhesh Poyarekar 70cc4d3
+  int len = seq->len;
Siddhesh Poyarekar 70cc4d3
+  size_t backw_stop = seq->backw_stop;
Siddhesh Poyarekar 70cc4d3
+  size_t backw = seq->backw;
Siddhesh Poyarekar 70cc4d3
+  size_t idxcnt = seq->idxcnt;
Siddhesh Poyarekar 70cc4d3
+  size_t idxmax = seq->idxmax;
Siddhesh Poyarekar 70cc4d3
+  size_t idxnow = seq->idxnow;
Siddhesh Poyarekar 70cc4d3
+  unsigned char *rulearr = seq->rulearr;
Siddhesh Poyarekar 70cc4d3
+  int32_t *idxarr = seq->idxarr;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  while (len == 0)
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      ++val;
Siddhesh Poyarekar 70cc4d3
+      if (backw_stop != ~0ul)
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  /* The is something pushed.  */
Siddhesh Poyarekar 70cc4d3
+	  if (backw == backw_stop)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* The last pushed character was handled.  Continue
Siddhesh Poyarekar 70cc4d3
+		 with forward characters.  */
Siddhesh Poyarekar 70cc4d3
+	      if (idxcnt < idxmax)
Siddhesh Poyarekar 70cc4d3
+		{
Siddhesh Poyarekar 70cc4d3
+		  idxnow = idxcnt;
Siddhesh Poyarekar 70cc4d3
+		  backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+		}
Siddhesh Poyarekar 70cc4d3
+	      else
Siddhesh Poyarekar 70cc4d3
+		{
Siddhesh Poyarekar 70cc4d3
+		  /* Nothing anymore.  The backward sequence
Siddhesh Poyarekar 70cc4d3
+		     ended with the last sequence in the string.  */
Siddhesh Poyarekar 70cc4d3
+		  idxnow = ~0ul;
Siddhesh Poyarekar 70cc4d3
+		  break;
Siddhesh Poyarekar 70cc4d3
+		}
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    idxnow = --backw;
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+      else
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  backw_stop = idxcnt;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	  while (idxcnt < idxmax)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      if ((rulesets[rulearr[idxcnt] * nrules + pass]
Siddhesh Poyarekar 70cc4d3
+		   & sort_backward) == 0)
Siddhesh Poyarekar 70cc4d3
+		/* No more backward characters to push.  */
Siddhesh Poyarekar 70cc4d3
+		break;
Siddhesh Poyarekar 70cc4d3
+	      ++idxcnt;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	  if (backw_stop == idxcnt)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* No sequence at all or just one.  */
Siddhesh Poyarekar 70cc4d3
+	      if (idxcnt == idxmax)
Siddhesh Poyarekar 70cc4d3
+		/* Note that seq1len is still zero.  */
Siddhesh Poyarekar 70cc4d3
+		break;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	      backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+	      idxnow = idxcnt++;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    /* We pushed backward sequences.  */
Siddhesh Poyarekar 70cc4d3
+	    idxnow = backw = idxcnt - 1;
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+      len = weights[idxarr[idxnow]++];
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  /* Update the structure.  */
Siddhesh Poyarekar 70cc4d3
+  seq->val = val;
Siddhesh Poyarekar 70cc4d3
+  seq->len = len;
Siddhesh Poyarekar 70cc4d3
+  seq->backw_stop = backw_stop;
Siddhesh Poyarekar 70cc4d3
+  seq->backw = backw;
Siddhesh Poyarekar 70cc4d3
+  seq->idxcnt = idxcnt;
Siddhesh Poyarekar 70cc4d3
+  seq->idxnow = idxnow;
Siddhesh Poyarekar 70cc4d3
+}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+/* Get next sequence.  Traverse the string as required.  */
Siddhesh Poyarekar 70cc4d3
+static void
Siddhesh Poyarekar 70cc4d3
+get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
Siddhesh Poyarekar 70cc4d3
+	      const USTRING_TYPE *weights, const int32_t *table,
Siddhesh Poyarekar 70cc4d3
+	      const USTRING_TYPE *extra, const int32_t *indirect)
Siddhesh Poyarekar 70cc4d3
+{
Siddhesh Poyarekar 70cc4d3
+#include WEIGHT_H
Siddhesh Poyarekar 70cc4d3
+  int val = seq->val = 0;
Siddhesh Poyarekar 70cc4d3
+  int len = seq->len;
Siddhesh Poyarekar 70cc4d3
+  size_t backw_stop = seq->backw_stop;
Siddhesh Poyarekar 70cc4d3
+  size_t backw = seq->backw;
Siddhesh Poyarekar 70cc4d3
+  size_t idxcnt = seq->idxcnt;
Siddhesh Poyarekar 70cc4d3
+  size_t idxmax = seq->idxmax;
Siddhesh Poyarekar 70cc4d3
+  size_t idxnow = seq->idxnow;
Siddhesh Poyarekar 70cc4d3
+  unsigned char *rulearr = seq->rulearr;
Siddhesh Poyarekar 70cc4d3
+  int32_t *idxarr = seq->idxarr;
Siddhesh Poyarekar 70cc4d3
+  const USTRING_TYPE *us = seq->us;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  while (len == 0)
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      ++val;
Siddhesh Poyarekar 70cc4d3
+      if (backw_stop != ~0ul)
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  /* The is something pushed.  */
Siddhesh Poyarekar 70cc4d3
+	  if (backw == backw_stop)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* The last pushed character was handled.  Continue
Siddhesh Poyarekar 70cc4d3
+		 with forward characters.  */
Siddhesh Poyarekar 70cc4d3
+	      if (idxcnt < idxmax)
Siddhesh Poyarekar 70cc4d3
+		{
Siddhesh Poyarekar 70cc4d3
+		  idxnow = idxcnt;
Siddhesh Poyarekar 70cc4d3
+		  backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+		}
Siddhesh Poyarekar 70cc4d3
+	      else
Siddhesh Poyarekar 70cc4d3
+		/* Nothing anymore.  The backward sequence ended with
Siddhesh Poyarekar 70cc4d3
+		   the last sequence in the string.  Note that seq2len
Siddhesh Poyarekar 70cc4d3
+		   is still zero.  */
Siddhesh Poyarekar 70cc4d3
+		break;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    idxnow = --backw;
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+      else
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  backw_stop = idxmax;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	  while (*us != L('\0'))
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      int32_t tmp = findidx (&us, -1);
Siddhesh Poyarekar 70cc4d3
+	      rulearr[idxmax] = tmp >> 24;
Siddhesh Poyarekar 70cc4d3
+	      idxarr[idxmax] = tmp & 0xffffff;
Siddhesh Poyarekar 70cc4d3
+	      idxcnt = idxmax++;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	      if ((rulesets[rulearr[idxcnt] * nrules]
Siddhesh Poyarekar 70cc4d3
+		   & sort_backward) == 0)
Siddhesh Poyarekar 70cc4d3
+		/* No more backward characters to push.  */
Siddhesh Poyarekar 70cc4d3
+		break;
Siddhesh Poyarekar 70cc4d3
+	      ++idxcnt;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	  if (backw_stop >= idxcnt)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* No sequence at all or just one.  */
Siddhesh Poyarekar 70cc4d3
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
Siddhesh Poyarekar 70cc4d3
+		/* Note that seq1len is still zero.  */
Siddhesh Poyarekar 70cc4d3
+		break;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	      backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+	      idxnow = idxcnt;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    /* We pushed backward sequences.  */
Siddhesh Poyarekar 70cc4d3
+	    idxnow = backw = idxcnt - 1;
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+      len = weights[idxarr[idxnow]++];
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  /* Update the structure.  */
Siddhesh Poyarekar 70cc4d3
+  seq->val = val;
Siddhesh Poyarekar 70cc4d3
+  seq->len = len;
Siddhesh Poyarekar 70cc4d3
+  seq->backw_stop = backw_stop;
Siddhesh Poyarekar 70cc4d3
+  seq->backw = backw;
Siddhesh Poyarekar 70cc4d3
+  seq->idxcnt = idxcnt;
Siddhesh Poyarekar 70cc4d3
+  seq->idxmax = idxmax;
Siddhesh Poyarekar 70cc4d3
+  seq->idxnow = idxnow;
Siddhesh Poyarekar 70cc4d3
+  seq->us = us;
Siddhesh Poyarekar 70cc4d3
+}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+/* Get next sequence.  Traverse the string as required.  This function does not
Siddhesh Poyarekar 70cc4d3
+   set or use any index or rule cache.  */
Siddhesh Poyarekar 70cc4d3
+static void
Siddhesh Poyarekar 70cc4d3
+get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
Siddhesh Poyarekar 70cc4d3
+		      const USTRING_TYPE *weights, const int32_t *table,
Siddhesh Poyarekar 70cc4d3
+		      const USTRING_TYPE *extra, const int32_t *indirect,
Siddhesh Poyarekar 70cc4d3
+		      int pass)
Siddhesh Poyarekar 70cc4d3
+{
Siddhesh Poyarekar 70cc4d3
+#include WEIGHT_H
Siddhesh Poyarekar 70cc4d3
+  int val = seq->val = 0;
Siddhesh Poyarekar 70cc4d3
+  int len = seq->len;
Siddhesh Poyarekar 70cc4d3
+  size_t backw_stop = seq->backw_stop;
Siddhesh Poyarekar 70cc4d3
+  size_t backw = seq->backw;
Siddhesh Poyarekar 70cc4d3
+  size_t idxcnt = seq->idxcnt;
Siddhesh Poyarekar 70cc4d3
+  size_t idxmax = seq->idxmax;
Siddhesh Poyarekar 70cc4d3
+  int32_t idx = seq->idx;
Siddhesh Poyarekar 70cc4d3
+  const USTRING_TYPE *us = seq->us;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  while (len == 0)
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      ++val;
Siddhesh Poyarekar 70cc4d3
+      if (backw_stop != ~0ul)
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  /* The is something pushed.  */
Siddhesh Poyarekar 70cc4d3
+	  if (backw == backw_stop)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* The last pushed character was handled.  Continue
Siddhesh Poyarekar 70cc4d3
+		 with forward characters.  */
Siddhesh Poyarekar 70cc4d3
+	      if (idxcnt < idxmax)
Siddhesh Poyarekar 70cc4d3
+		{
Siddhesh Poyarekar 70cc4d3
+		  idx = seq->save_idx;
Siddhesh Poyarekar 70cc4d3
+		  backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+		}
Siddhesh Poyarekar 70cc4d3
+	      else
Siddhesh Poyarekar 70cc4d3
+		{
Siddhesh Poyarekar 70cc4d3
+		  /* Nothing anymore.  The backward sequence ended with
Siddhesh Poyarekar 70cc4d3
+		     the last sequence in the string.  Note that len is
Siddhesh Poyarekar 70cc4d3
+		     still zero.  */
Siddhesh Poyarekar 70cc4d3
+		  idx = 0;
Siddhesh Poyarekar 70cc4d3
+		  break;
Siddhesh Poyarekar 70cc4d3
+	        }
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* XXX Traverse BACKW sequences from the beginning of
Siddhesh Poyarekar 70cc4d3
+		 BACKW_STOP to get the next sequence.  Is ther a quicker way
Siddhesh Poyarekar 70cc4d3
+	         to do this?  */
Siddhesh Poyarekar 70cc4d3
+	      int i = backw_stop;
Siddhesh Poyarekar 70cc4d3
+	      us = seq->back_us;
Siddhesh Poyarekar 70cc4d3
+	      while (i < backw)
Siddhesh Poyarekar 70cc4d3
+		{
Siddhesh Poyarekar 70cc4d3
+		  int32_t tmp = findidx (&us, -1);
Siddhesh Poyarekar 70cc4d3
+		  idx = tmp & 0xffffff;
Siddhesh Poyarekar 70cc4d3
+		  i++;
Siddhesh Poyarekar 70cc4d3
+		}
Siddhesh Poyarekar 70cc4d3
+	      --backw;
Siddhesh Poyarekar 70cc4d3
+	      us = seq->us;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+      else
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  backw_stop = idxmax;
Siddhesh Poyarekar 70cc4d3
+	  int32_t prev_idx = idx;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	  while (*us != L('\0'))
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      int32_t tmp = findidx (&us, -1);
Siddhesh Poyarekar 70cc4d3
+	      unsigned char rule = tmp >> 24;
Siddhesh Poyarekar 70cc4d3
+	      prev_idx = idx;
Siddhesh Poyarekar 70cc4d3
+	      idx = tmp & 0xffffff;
Siddhesh Poyarekar 70cc4d3
+	      idxcnt = idxmax++;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	      /* Save the rule for the first sequence.  */
Siddhesh Poyarekar 70cc4d3
+	      if (__glibc_unlikely (idxcnt == 0))
Siddhesh Poyarekar 70cc4d3
+	        seq->rule = rule;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	      if ((rulesets[rule * nrules + pass]
Siddhesh Poyarekar 70cc4d3
+		   & sort_backward) == 0)
Siddhesh Poyarekar 70cc4d3
+		/* No more backward characters to push.  */
Siddhesh Poyarekar 70cc4d3
+		break;
Siddhesh Poyarekar 70cc4d3
+	      ++idxcnt;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	  if (backw_stop >= idxcnt)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* No sequence at all or just one.  */
Siddhesh Poyarekar 70cc4d3
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
Siddhesh Poyarekar 70cc4d3
+		/* Note that len is still zero.  */
Siddhesh Poyarekar 70cc4d3
+		break;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+	      backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      /* We pushed backward sequences.  If the stream ended with the
Siddhesh Poyarekar 70cc4d3
+		 backward sequence, then we process the last sequence we
Siddhesh Poyarekar 70cc4d3
+		 found.  Otherwise we process the sequence before the last
Siddhesh Poyarekar 70cc4d3
+		 one since the last one was a forward sequence.  */
Siddhesh Poyarekar 70cc4d3
+	      seq->back_us = seq->us;
Siddhesh Poyarekar 70cc4d3
+	      seq->us = us;
Siddhesh Poyarekar 70cc4d3
+	      backw = idxcnt;
Siddhesh Poyarekar 70cc4d3
+	      if (idxmax > idxcnt)
Siddhesh Poyarekar 70cc4d3
+		{
Siddhesh Poyarekar 70cc4d3
+		  backw--;
Siddhesh Poyarekar 70cc4d3
+		  seq->save_idx = idx;
Siddhesh Poyarekar 70cc4d3
+		  idx = prev_idx;
Siddhesh Poyarekar 70cc4d3
+		}
Siddhesh Poyarekar 70cc4d3
+	      if (backw > backw_stop)
Siddhesh Poyarekar 70cc4d3
+		backw--;
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+      len = weights[idx++];
Siddhesh Poyarekar 70cc4d3
+      /* Skip over indeces of previous levels.  */
Siddhesh Poyarekar 70cc4d3
+      for (int i = 0; i < pass; i++)
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  idx += len;
Siddhesh Poyarekar 70cc4d3
+	  len = weights[idx];
Siddhesh Poyarekar 70cc4d3
+	  idx++;
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  /* Update the structure.  */
Siddhesh Poyarekar 70cc4d3
+  seq->val = val;
Siddhesh Poyarekar 70cc4d3
+  seq->len = len;
Siddhesh Poyarekar 70cc4d3
+  seq->backw_stop = backw_stop;
Siddhesh Poyarekar 70cc4d3
+  seq->backw = backw;
Siddhesh Poyarekar 70cc4d3
+  seq->idxcnt = idxcnt;
Siddhesh Poyarekar 70cc4d3
+  seq->idxmax = idxmax;
Siddhesh Poyarekar 70cc4d3
+  seq->us = us;
Siddhesh Poyarekar 70cc4d3
+  seq->idx = idx;
Siddhesh Poyarekar 70cc4d3
+}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+/* Compare two sequences.  This version does not use the index and rules
Siddhesh Poyarekar 70cc4d3
+   cache.  */
Siddhesh Poyarekar 70cc4d3
+static int
Siddhesh Poyarekar 70cc4d3
+do_compare_nocache (coll_seq *seq1, coll_seq *seq2, int position,
Siddhesh Poyarekar 70cc4d3
+		    const USTRING_TYPE *weights)
Siddhesh Poyarekar 70cc4d3
+{
Siddhesh Poyarekar 70cc4d3
+  int seq1len = seq1->len;
Siddhesh Poyarekar 70cc4d3
+  int seq2len = seq2->len;
Siddhesh Poyarekar 70cc4d3
+  int val1 = seq1->val;
Siddhesh Poyarekar 70cc4d3
+  int val2 = seq2->val;
Siddhesh Poyarekar 70cc4d3
+  int idx1 = seq1->idx;
Siddhesh Poyarekar 70cc4d3
+  int idx2 = seq2->idx;
Siddhesh Poyarekar 70cc4d3
+  int result = 0;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  /* Test for position if necessary.  */
Siddhesh Poyarekar 70cc4d3
+  if (position && val1 != val2)
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      result = val1 - val2;
Siddhesh Poyarekar 70cc4d3
+      goto out;
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  /* Compare the two sequences.  */
Siddhesh Poyarekar 70cc4d3
+  do
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      if (weights[idx1] != weights[idx2])
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  /* The sequences differ.  */
Siddhesh Poyarekar 70cc4d3
+	  result = weights[idx1] - weights[idx2];
Siddhesh Poyarekar 70cc4d3
+	  goto out;
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+      /* Increment the offsets.  */
Siddhesh Poyarekar 70cc4d3
+      ++idx1;
Siddhesh Poyarekar 70cc4d3
+      ++idx2;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+      --seq1len;
Siddhesh Poyarekar 70cc4d3
+      --seq2len;
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
+  while (seq1len > 0 && seq2len > 0);
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  if (position && seq1len != seq2len)
Siddhesh Poyarekar 70cc4d3
+    result = seq1len - seq2len;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+out:
Siddhesh Poyarekar 70cc4d3
+  seq1->len = seq1len;
Siddhesh Poyarekar 70cc4d3
+  seq2->len = seq2len;
Siddhesh Poyarekar 70cc4d3
+  seq1->idx = idx1;
Siddhesh Poyarekar 70cc4d3
+  seq2->idx = idx2;
Siddhesh Poyarekar 70cc4d3
+  return result;
Siddhesh Poyarekar 70cc4d3
+}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+/* Compare two sequences using the index cache.  */
Siddhesh Poyarekar 70cc4d3
+static int
Siddhesh Poyarekar 70cc4d3
+do_compare (coll_seq *seq1, coll_seq *seq2, int position,
Siddhesh Poyarekar 70cc4d3
+	    const USTRING_TYPE *weights)
Siddhesh Poyarekar 70cc4d3
+{
Siddhesh Poyarekar 70cc4d3
+  int seq1len = seq1->len;
Siddhesh Poyarekar 70cc4d3
+  int seq2len = seq2->len;
Siddhesh Poyarekar 70cc4d3
+  int val1 = seq1->val;
Siddhesh Poyarekar 70cc4d3
+  int val2 = seq2->val;
Siddhesh Poyarekar 70cc4d3
+  int32_t *idx1arr = seq1->idxarr;
Siddhesh Poyarekar 70cc4d3
+  int32_t *idx2arr = seq2->idxarr;
Siddhesh Poyarekar 70cc4d3
+  int idx1now = seq1->idxnow;
Siddhesh Poyarekar 70cc4d3
+  int idx2now = seq2->idxnow;
Siddhesh Poyarekar 70cc4d3
+  int result = 0;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  /* Test for position if necessary.  */
Siddhesh Poyarekar 70cc4d3
+  if (position && val1 != val2)
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      result = val1 - val2;
Siddhesh Poyarekar 70cc4d3
+      goto out;
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  /* Compare the two sequences.  */
Siddhesh Poyarekar 70cc4d3
+  do
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
Siddhesh Poyarekar 70cc4d3
+	{
Siddhesh Poyarekar 70cc4d3
+	  /* The sequences differ.  */
Siddhesh Poyarekar 70cc4d3
+	  result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
Siddhesh Poyarekar 70cc4d3
+	  goto out;
Siddhesh Poyarekar 70cc4d3
+	}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+      /* Increment the offsets.  */
Siddhesh Poyarekar 70cc4d3
+      ++idx1arr[idx1now];
Siddhesh Poyarekar 70cc4d3
+      ++idx2arr[idx2now];
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+      --seq1len;
Siddhesh Poyarekar 70cc4d3
+      --seq2len;
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
+  while (seq1len > 0 && seq2len > 0);
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+  if (position && seq1len != seq2len)
Siddhesh Poyarekar 70cc4d3
+    result = seq1len - seq2len;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+out:
Siddhesh Poyarekar 70cc4d3
+  seq1->len = seq1len;
Siddhesh Poyarekar 70cc4d3
+  seq2->len = seq2len;
Siddhesh Poyarekar 70cc4d3
+  return result;
Siddhesh Poyarekar 70cc4d3
+}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
 int
Siddhesh Poyarekar 70cc4d3
-STRCOLL (s1, s2, l)
Siddhesh Poyarekar 70cc4d3
-     const STRING_TYPE *s1;
Siddhesh Poyarekar 70cc4d3
-     const STRING_TYPE *s2;
Siddhesh Poyarekar 70cc4d3
-     __locale_t l;
Siddhesh Poyarekar 70cc4d3
+STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
Siddhesh Poyarekar 70cc4d3
 {
Siddhesh Poyarekar 70cc4d3
   struct __locale_data *current = l->__locales[LC_COLLATE];
Siddhesh Poyarekar 70cc4d3
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
Siddhesh Poyarekar 70cc4d3
@@ -56,34 +479,6 @@ STRCOLL (s1, s2, l)
Siddhesh Poyarekar 70cc4d3
   const USTRING_TYPE *weights;
Siddhesh Poyarekar 70cc4d3
   const USTRING_TYPE *extra;
Siddhesh Poyarekar 70cc4d3
   const int32_t *indirect;
Siddhesh Poyarekar 70cc4d3
-  uint_fast32_t pass;
Siddhesh Poyarekar 70cc4d3
-  int result = 0;
Siddhesh Poyarekar 70cc4d3
-  const USTRING_TYPE *us1;
Siddhesh Poyarekar 70cc4d3
-  const USTRING_TYPE *us2;
Siddhesh Poyarekar 70cc4d3
-  size_t s1len;
Siddhesh Poyarekar 70cc4d3
-  size_t s2len;
Siddhesh Poyarekar 70cc4d3
-  int32_t *idx1arr;
Siddhesh Poyarekar 70cc4d3
-  int32_t *idx2arr;
Siddhesh Poyarekar 70cc4d3
-  unsigned char *rule1arr;
Siddhesh Poyarekar 70cc4d3
-  unsigned char *rule2arr;
Siddhesh Poyarekar 70cc4d3
-  size_t idx1max;
Siddhesh Poyarekar 70cc4d3
-  size_t idx2max;
Siddhesh Poyarekar 70cc4d3
-  size_t idx1cnt;
Siddhesh Poyarekar 70cc4d3
-  size_t idx2cnt;
Siddhesh Poyarekar 70cc4d3
-  size_t idx1now;
Siddhesh Poyarekar 70cc4d3
-  size_t idx2now;
Siddhesh Poyarekar 70cc4d3
-  size_t backw1_stop;
Siddhesh Poyarekar 70cc4d3
-  size_t backw2_stop;
Siddhesh Poyarekar 70cc4d3
-  size_t backw1;
Siddhesh Poyarekar 70cc4d3
-  size_t backw2;
Siddhesh Poyarekar 70cc4d3
-  int val1;
Siddhesh Poyarekar 70cc4d3
-  int val2;
Siddhesh Poyarekar 70cc4d3
-  int position;
Siddhesh Poyarekar 70cc4d3
-  int seq1len;
Siddhesh Poyarekar 70cc4d3
-  int seq2len;
Siddhesh Poyarekar 70cc4d3
-  int use_malloc;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-#include WEIGHT_H
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
   if (nrules == 0)
Siddhesh Poyarekar 70cc4d3
     return STRCMP (s1, s2);
Siddhesh Poyarekar 70cc4d3
@@ -98,7 +493,6 @@ STRCOLL (s1, s2, l)
Siddhesh Poyarekar 70cc4d3
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
Siddhesh Poyarekar 70cc4d3
   indirect = (const int32_t *)
Siddhesh Poyarekar 70cc4d3
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
Siddhesh Poyarekar 70cc4d3
-  use_malloc = 0;
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
   assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
Siddhesh Poyarekar 70cc4d3
   assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
Siddhesh Poyarekar 70cc4d3
@@ -106,18 +500,13 @@ STRCOLL (s1, s2, l)
Siddhesh Poyarekar 70cc4d3
   assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
   /* We need this a few times.  */
Siddhesh Poyarekar 70cc4d3
-  s1len = STRLEN (s1);
Siddhesh Poyarekar 70cc4d3
-  s2len = STRLEN (s2);
Siddhesh Poyarekar 70cc4d3
+  size_t s1len = STRLEN (s1);
Siddhesh Poyarekar 70cc4d3
+  size_t s2len = STRLEN (s2);
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
   /* Catch empty strings.  */
Siddhesh Poyarekar 70cc4d3
-  if (__builtin_expect (s1len == 0, 0) || __builtin_expect (s2len == 0, 0))
Siddhesh Poyarekar 70cc4d3
+  if (__glibc_unlikely (s1len == 0) || __glibc_unlikely (s2len == 0))
Siddhesh Poyarekar 70cc4d3
     return (s1len != 0) - (s2len != 0);
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-  /* We need the elements of the strings as unsigned values since they
Siddhesh Poyarekar 70cc4d3
-     are used as indeces.  */
Siddhesh Poyarekar 70cc4d3
-  us1 = (const USTRING_TYPE *) s1;
Siddhesh Poyarekar 70cc4d3
-  us2 = (const USTRING_TYPE *) s2;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
   /* Perform the first pass over the string and while doing this find
Siddhesh Poyarekar 70cc4d3
      and store the weights for each character.  Since we want this to
Siddhesh Poyarekar 70cc4d3
      be as fast as possible we are using `alloca' to store the temporary
Siddhesh Poyarekar 70cc4d3
@@ -127,411 +516,124 @@ STRCOLL (s1, s2, l)
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
      Please note that the localedef programs makes sure that `position'
Siddhesh Poyarekar 70cc4d3
      is not used at the first level.  */
Siddhesh Poyarekar 70cc4d3
-  if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
Siddhesh Poyarekar 70cc4d3
-    {
Siddhesh Poyarekar 70cc4d3
-      idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
Siddhesh Poyarekar 70cc4d3
-      idx2arr = &idx1arr[s1len];
Siddhesh Poyarekar 70cc4d3
-      rule1arr = (unsigned char *) &idx2arr[s2len];
Siddhesh Poyarekar 70cc4d3
-      rule2arr = &rule1arr[s1len];
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-      if (idx1arr == NULL)
Siddhesh Poyarekar 70cc4d3
-	/* No memory.  Well, go with the stack then.
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	   XXX Once this implementation is stable we will handle this
Siddhesh Poyarekar 70cc4d3
-	   differently.  Instead of precomputing the indeces we will
Siddhesh Poyarekar 70cc4d3
-	   do this in time.  This means, though, that this happens for
Siddhesh Poyarekar 70cc4d3
-	   every pass again.  */
Siddhesh Poyarekar 70cc4d3
-	goto try_stack;
Siddhesh Poyarekar 70cc4d3
-      use_malloc = 1;
Siddhesh Poyarekar 70cc4d3
-    }
Siddhesh Poyarekar 70cc4d3
-  else
Siddhesh Poyarekar 70cc4d3
-    {
Siddhesh Poyarekar 70cc4d3
-    try_stack:
Siddhesh Poyarekar 70cc4d3
-      idx1arr = (int32_t *) alloca (s1len * sizeof (int32_t));
Siddhesh Poyarekar 70cc4d3
-      idx2arr = (int32_t *) alloca (s2len * sizeof (int32_t));
Siddhesh Poyarekar 70cc4d3
-      rule1arr = (unsigned char *) alloca (s1len);
Siddhesh Poyarekar 70cc4d3
-      rule2arr = (unsigned char *) alloca (s2len);
Siddhesh Poyarekar 70cc4d3
-    }
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-  idx1cnt = 0;
Siddhesh Poyarekar 70cc4d3
-  idx2cnt = 0;
Siddhesh Poyarekar 70cc4d3
-  idx1max = 0;
Siddhesh Poyarekar 70cc4d3
-  idx2max = 0;
Siddhesh Poyarekar 70cc4d3
-  idx1now = 0;
Siddhesh Poyarekar 70cc4d3
-  idx2now = 0;
Siddhesh Poyarekar 70cc4d3
-  backw1_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-  backw2_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-  backw1 = ~0ul;
Siddhesh Poyarekar 70cc4d3
-  backw2 = ~0ul;
Siddhesh Poyarekar 70cc4d3
-  seq1len = 0;
Siddhesh Poyarekar 70cc4d3
-  seq2len = 0;
Siddhesh Poyarekar 70cc4d3
-  position = rulesets[0] & sort_position;
Siddhesh Poyarekar 70cc4d3
-  while (1)
Siddhesh Poyarekar 70cc4d3
-    {
Siddhesh Poyarekar 70cc4d3
-      val1 = 0;
Siddhesh Poyarekar 70cc4d3
-      val2 = 0;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-      /* Get the next non-IGNOREd element for string `s1'.  */
Siddhesh Poyarekar 70cc4d3
-      if (seq1len == 0)
Siddhesh Poyarekar 70cc4d3
-	do
Siddhesh Poyarekar 70cc4d3
-	  {
Siddhesh Poyarekar 70cc4d3
-	    ++val1;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	    if (backw1_stop != ~0ul)
Siddhesh Poyarekar 70cc4d3
-	      {
Siddhesh Poyarekar 70cc4d3
-		/* The is something pushed.  */
Siddhesh Poyarekar 70cc4d3
-		if (backw1 == backw1_stop)
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    /* The last pushed character was handled.  Continue
Siddhesh Poyarekar 70cc4d3
-		       with forward characters.  */
Siddhesh Poyarekar 70cc4d3
-		    if (idx1cnt < idx1max)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			idx1now = idx1cnt;
Siddhesh Poyarekar 70cc4d3
-			backw1_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-		    else
Siddhesh Poyarekar 70cc4d3
-		      /* Nothing anymore.  The backward sequence ended with
Siddhesh Poyarekar 70cc4d3
-			 the last sequence in the string.  Note that seq1len
Siddhesh Poyarekar 70cc4d3
-			 is still zero.  */
Siddhesh Poyarekar 70cc4d3
-		      break;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-		else
Siddhesh Poyarekar 70cc4d3
-		  idx1now = --backw1;
Siddhesh Poyarekar 70cc4d3
-	      }
Siddhesh Poyarekar 70cc4d3
-	    else
Siddhesh Poyarekar 70cc4d3
-	      {
Siddhesh Poyarekar 70cc4d3
-		backw1_stop = idx1max;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		while (*us1 != L('\0'))
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    int32_t tmp = findidx (&us1, -1);
Siddhesh Poyarekar 70cc4d3
-		    rule1arr[idx1max] = tmp >> 24;
Siddhesh Poyarekar 70cc4d3
-		    idx1arr[idx1max] = tmp & 0xffffff;
Siddhesh Poyarekar 70cc4d3
-		    idx1cnt = idx1max++;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    if ((rulesets[rule1arr[idx1cnt] * nrules]
Siddhesh Poyarekar 70cc4d3
-			 & sort_backward) == 0)
Siddhesh Poyarekar 70cc4d3
-		      /* No more backward characters to push.  */
Siddhesh Poyarekar 70cc4d3
-		      break;
Siddhesh Poyarekar 70cc4d3
-		    ++idx1cnt;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		if (backw1_stop >= idx1cnt)
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    /* No sequence at all or just one.  */
Siddhesh Poyarekar 70cc4d3
-		    if (idx1cnt == idx1max || backw1_stop > idx1cnt)
Siddhesh Poyarekar 70cc4d3
-		      /* Note that seq1len is still zero.  */
Siddhesh Poyarekar 70cc4d3
-		      break;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    backw1_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-		    idx1now = idx1cnt;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-		else
Siddhesh Poyarekar 70cc4d3
-		  /* We pushed backward sequences.  */
Siddhesh Poyarekar 70cc4d3
-		  idx1now = backw1 = idx1cnt - 1;
Siddhesh Poyarekar 70cc4d3
-	      }
Siddhesh Poyarekar 70cc4d3
-	  }
Siddhesh Poyarekar 70cc4d3
-	while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-      /* And the same for string `s2'.  */
Siddhesh Poyarekar 70cc4d3
-      if (seq2len == 0)
Siddhesh Poyarekar 70cc4d3
-	do
Siddhesh Poyarekar 70cc4d3
-	  {
Siddhesh Poyarekar 70cc4d3
-	    ++val2;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	    if (backw2_stop != ~0ul)
Siddhesh Poyarekar 70cc4d3
-	      {
Siddhesh Poyarekar 70cc4d3
-		/* The is something pushed.  */
Siddhesh Poyarekar 70cc4d3
-		if (backw2 == backw2_stop)
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    /* The last pushed character was handled.  Continue
Siddhesh Poyarekar 70cc4d3
-		       with forward characters.  */
Siddhesh Poyarekar 70cc4d3
-		    if (idx2cnt < idx2max)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			idx2now = idx2cnt;
Siddhesh Poyarekar 70cc4d3
-			backw2_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-		    else
Siddhesh Poyarekar 70cc4d3
-		      /* Nothing anymore.  The backward sequence ended with
Siddhesh Poyarekar 70cc4d3
-			 the last sequence in the string.  Note that seq2len
Siddhesh Poyarekar 70cc4d3
-			 is still zero.  */
Siddhesh Poyarekar 70cc4d3
-		      break;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-		else
Siddhesh Poyarekar 70cc4d3
-		  idx2now = --backw2;
Siddhesh Poyarekar 70cc4d3
-	      }
Siddhesh Poyarekar 70cc4d3
-	    else
Siddhesh Poyarekar 70cc4d3
-	      {
Siddhesh Poyarekar 70cc4d3
-		backw2_stop = idx2max;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		while (*us2 != L('\0'))
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    int32_t tmp = findidx (&us2, -1);
Siddhesh Poyarekar 70cc4d3
-		    rule2arr[idx2max] = tmp >> 24;
Siddhesh Poyarekar 70cc4d3
-		    idx2arr[idx2max] = tmp & 0xffffff;
Siddhesh Poyarekar 70cc4d3
-		    idx2cnt = idx2max++;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    if ((rulesets[rule2arr[idx2cnt] * nrules]
Siddhesh Poyarekar 70cc4d3
-			 & sort_backward) == 0)
Siddhesh Poyarekar 70cc4d3
-		      /* No more backward characters to push.  */
Siddhesh Poyarekar 70cc4d3
-		      break;
Siddhesh Poyarekar 70cc4d3
-		    ++idx2cnt;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		if (backw2_stop >= idx2cnt)
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    /* No sequence at all or just one.  */
Siddhesh Poyarekar 70cc4d3
-		    if (idx2cnt == idx2max || backw2_stop > idx2cnt)
Siddhesh Poyarekar 70cc4d3
-		      /* Note that seq1len is still zero.  */
Siddhesh Poyarekar 70cc4d3
-		      break;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    backw2_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-		    idx2now = idx2cnt;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-		else
Siddhesh Poyarekar 70cc4d3
-		  /* We pushed backward sequences.  */
Siddhesh Poyarekar 70cc4d3
-		  idx2now = backw2 = idx2cnt - 1;
Siddhesh Poyarekar 70cc4d3
-	      }
Siddhesh Poyarekar 70cc4d3
-	  }
Siddhesh Poyarekar 70cc4d3
-	while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-      /* See whether any or both strings are empty.  */
Siddhesh Poyarekar 70cc4d3
-      if (seq1len == 0 || seq2len == 0)
Siddhesh Poyarekar 70cc4d3
-	{
Siddhesh Poyarekar 70cc4d3
-	  if (seq1len == seq2len)
Siddhesh Poyarekar 70cc4d3
-	    /* Both ended.  So far so good, both strings are equal at the
Siddhesh Poyarekar 70cc4d3
-	       first level.  */
Siddhesh Poyarekar 70cc4d3
-	    break;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	  /* This means one string is shorter than the other.  Find out
Siddhesh Poyarekar 70cc4d3
-	     which one and return an appropriate value.  */
Siddhesh Poyarekar 70cc4d3
-	  result = seq1len == 0 ? -1 : 1;
Siddhesh Poyarekar 70cc4d3
-	  goto free_and_return;
Siddhesh Poyarekar 70cc4d3
-	}
Siddhesh Poyarekar 70cc4d3
+  coll_seq seq1, seq2;
Siddhesh Poyarekar 70cc4d3
+  bool use_malloc = false;
Siddhesh Poyarekar 70cc4d3
+  int result = 0;
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-      /* Test for position if necessary.  */
Siddhesh Poyarekar 70cc4d3
-      if (position && val1 != val2)
Siddhesh Poyarekar 70cc4d3
-	{
Siddhesh Poyarekar 70cc4d3
-	  result = val1 - val2;
Siddhesh Poyarekar 70cc4d3
-	  goto free_and_return;
Siddhesh Poyarekar 70cc4d3
-	}
Siddhesh Poyarekar 70cc4d3
+  memset (&seq1, 0, sizeof (seq1));
Siddhesh Poyarekar 70cc4d3
+  seq2 = seq1;
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-      /* Compare the two sequences.  */
Siddhesh Poyarekar 70cc4d3
-      do
Siddhesh Poyarekar 70cc4d3
-	{
Siddhesh Poyarekar 70cc4d3
-	  if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
Siddhesh Poyarekar 70cc4d3
-	    {
Siddhesh Poyarekar 70cc4d3
-	      /* The sequences differ.  */
Siddhesh Poyarekar 70cc4d3
-	      result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
Siddhesh Poyarekar 70cc4d3
-	      goto free_and_return;
Siddhesh Poyarekar 70cc4d3
-	    }
Siddhesh Poyarekar 70cc4d3
+  size_t size_max = SIZE_MAX / (sizeof (int32_t) + 1);
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-	  /* Increment the offsets.  */
Siddhesh Poyarekar 70cc4d3
-	  ++idx1arr[idx1now];
Siddhesh Poyarekar 70cc4d3
-	  ++idx2arr[idx2now];
Siddhesh Poyarekar 70cc4d3
+  /* If the strings are long enough to cause overflow in the size request, then
Siddhesh Poyarekar 70cc4d3
+     skip the allocation and proceed with the non-cached routines.  */
Siddhesh Poyarekar 70cc4d3
+  if (MIN (s1len, s2len) > size_max
Siddhesh Poyarekar 70cc4d3
+      || MAX (s1len, s2len) > size_max - MIN (s1len, s2len))
Siddhesh Poyarekar 70cc4d3
+    goto begin_collate;
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-	  --seq1len;
Siddhesh Poyarekar 70cc4d3
-	  --seq2len;
Siddhesh Poyarekar 70cc4d3
-	}
Siddhesh Poyarekar 70cc4d3
-      while (seq1len > 0 && seq2len > 0);
Siddhesh Poyarekar 70cc4d3
+  if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-      if (position && seq1len != seq2len)
Siddhesh Poyarekar 70cc4d3
+      /* If we failed to allocate memory, we leave everything as NULL so that
Siddhesh Poyarekar 70cc4d3
+	 we use the nocache version of traversal and comparison functions.  */
Siddhesh Poyarekar 70cc4d3
+      if (seq1.idxarr != NULL)
Siddhesh Poyarekar 70cc4d3
 	{
Siddhesh Poyarekar 70cc4d3
-	  result = seq1len - seq2len;
Siddhesh Poyarekar 70cc4d3
-	  goto free_and_return;
Siddhesh Poyarekar 70cc4d3
+	  seq2.idxarr = &seq1.idxarr[s1len];
Siddhesh Poyarekar 70cc4d3
+	  seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
Siddhesh Poyarekar 70cc4d3
+	  seq2.rulearr = &seq1.rulearr[s1len];
Siddhesh Poyarekar 70cc4d3
+	  use_malloc = true;
Siddhesh Poyarekar 70cc4d3
 	}
Siddhesh Poyarekar 70cc4d3
     }
Siddhesh Poyarekar 70cc4d3
+  else
Siddhesh Poyarekar 70cc4d3
+    {
Siddhesh Poyarekar 70cc4d3
+      seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
Siddhesh Poyarekar 70cc4d3
+      seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
Siddhesh Poyarekar 70cc4d3
+      seq1.rulearr = (unsigned char *) alloca (s1len);
Siddhesh Poyarekar 70cc4d3
+      seq2.rulearr = (unsigned char *) alloca (s2len);
Siddhesh Poyarekar 70cc4d3
+    }
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-  /* Now the remaining passes over the weights.  We now use the
Siddhesh Poyarekar 70cc4d3
-     indeces we found before.  */
Siddhesh Poyarekar 70cc4d3
-  for (pass = 1; pass < nrules; ++pass)
Siddhesh Poyarekar 70cc4d3
+  int rule;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+ begin_collate:
Siddhesh Poyarekar 70cc4d3
+  rule = 0;
Siddhesh Poyarekar 70cc4d3
+  /* Cache values in the first pass and if needed, use them in subsequent
Siddhesh Poyarekar 70cc4d3
+     passes.  */
Siddhesh Poyarekar 70cc4d3
+  for (int pass = 0; pass < nrules; ++pass)
Siddhesh Poyarekar 70cc4d3
     {
Siddhesh Poyarekar 70cc4d3
+      seq1.idxcnt = 0;
Siddhesh Poyarekar 70cc4d3
+      seq1.idx = 0;
Siddhesh Poyarekar 70cc4d3
+      seq1.idx = 0;
Siddhesh Poyarekar 70cc4d3
+      seq1.backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+      seq1.backw = ~0ul;
Siddhesh Poyarekar 70cc4d3
+      seq2.idxcnt = 0;
Siddhesh Poyarekar 70cc4d3
+      seq2.backw_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
+      seq2.backw = ~0ul;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+      /* We need the elements of the strings as unsigned values since they
Siddhesh Poyarekar 70cc4d3
+	 are used as indeces.  */
Siddhesh Poyarekar 70cc4d3
+      seq1.us = (const USTRING_TYPE *) s1;
Siddhesh Poyarekar 70cc4d3
+      seq2.us = (const USTRING_TYPE *) s2;
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
       /* We assume that if a rule has defined `position' in one section
Siddhesh Poyarekar 70cc4d3
 	 this is true for all of them.  */
Siddhesh Poyarekar 70cc4d3
-      idx1cnt = 0;
Siddhesh Poyarekar 70cc4d3
-      idx2cnt = 0;
Siddhesh Poyarekar 70cc4d3
-      backw1_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-      backw2_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-      backw1 = ~0ul;
Siddhesh Poyarekar 70cc4d3
-      backw2 = ~0ul;
Siddhesh Poyarekar 70cc4d3
-      position = rulesets[rule1arr[0] * nrules + pass] & sort_position;
Siddhesh Poyarekar 70cc4d3
+      int position = rulesets[rule * nrules + pass] & sort_position;
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
       while (1)
Siddhesh Poyarekar 70cc4d3
 	{
Siddhesh Poyarekar 70cc4d3
-	  val1 = 0;
Siddhesh Poyarekar 70cc4d3
-	  val2 = 0;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	  /* Get the next non-IGNOREd element for string `s1'.  */
Siddhesh Poyarekar 70cc4d3
-	  if (seq1len == 0)
Siddhesh Poyarekar 70cc4d3
-	    do
Siddhesh Poyarekar 70cc4d3
-	      {
Siddhesh Poyarekar 70cc4d3
-		++val1;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		if (backw1_stop != ~0ul)
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    /* The is something pushed.  */
Siddhesh Poyarekar 70cc4d3
-		    if (backw1 == backw1_stop)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			/* The last pushed character was handled.  Continue
Siddhesh Poyarekar 70cc4d3
-			   with forward characters.  */
Siddhesh Poyarekar 70cc4d3
-			if (idx1cnt < idx1max)
Siddhesh Poyarekar 70cc4d3
-			  {
Siddhesh Poyarekar 70cc4d3
-			    idx1now = idx1cnt;
Siddhesh Poyarekar 70cc4d3
-			    backw1_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-			  }
Siddhesh Poyarekar 70cc4d3
-			else
Siddhesh Poyarekar 70cc4d3
-			  {
Siddhesh Poyarekar 70cc4d3
-			    /* Nothing anymore.  The backward sequence
Siddhesh Poyarekar 70cc4d3
-			       ended with the last sequence in the string.  */
Siddhesh Poyarekar 70cc4d3
-			    idx1now = ~0ul;
Siddhesh Poyarekar 70cc4d3
-			    break;
Siddhesh Poyarekar 70cc4d3
-			  }
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-		    else
Siddhesh Poyarekar 70cc4d3
-		      idx1now = --backw1;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-		else
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    backw1_stop = idx1cnt;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    while (idx1cnt < idx1max)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			if ((rulesets[rule1arr[idx1cnt] * nrules + pass]
Siddhesh Poyarekar 70cc4d3
-			     & sort_backward) == 0)
Siddhesh Poyarekar 70cc4d3
-			  /* No more backward characters to push.  */
Siddhesh Poyarekar 70cc4d3
-			  break;
Siddhesh Poyarekar 70cc4d3
-			++idx1cnt;
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    if (backw1_stop == idx1cnt)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			/* No sequence at all or just one.  */
Siddhesh Poyarekar 70cc4d3
-			if (idx1cnt == idx1max)
Siddhesh Poyarekar 70cc4d3
-			  /* Note that seq1len is still zero.  */
Siddhesh Poyarekar 70cc4d3
-			  break;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-			backw1_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-			idx1now = idx1cnt++;
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-		    else
Siddhesh Poyarekar 70cc4d3
-		      /* We pushed backward sequences.  */
Siddhesh Poyarekar 70cc4d3
-		      idx1now = backw1 = idx1cnt - 1;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-	      }
Siddhesh Poyarekar 70cc4d3
-	    while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	  /* And the same for string `s2'.  */
Siddhesh Poyarekar 70cc4d3
-	  if (seq2len == 0)
Siddhesh Poyarekar 70cc4d3
-	    do
Siddhesh Poyarekar 70cc4d3
-	      {
Siddhesh Poyarekar 70cc4d3
-		++val2;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		if (backw2_stop != ~0ul)
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    /* The is something pushed.  */
Siddhesh Poyarekar 70cc4d3
-		    if (backw2 == backw2_stop)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			/* The last pushed character was handled.  Continue
Siddhesh Poyarekar 70cc4d3
-			   with forward characters.  */
Siddhesh Poyarekar 70cc4d3
-			if (idx2cnt < idx2max)
Siddhesh Poyarekar 70cc4d3
-			  {
Siddhesh Poyarekar 70cc4d3
-			    idx2now = idx2cnt;
Siddhesh Poyarekar 70cc4d3
-			    backw2_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-			  }
Siddhesh Poyarekar 70cc4d3
-			else
Siddhesh Poyarekar 70cc4d3
-			  {
Siddhesh Poyarekar 70cc4d3
-			    /* Nothing anymore.  The backward sequence
Siddhesh Poyarekar 70cc4d3
-			       ended with the last sequence in the string.  */
Siddhesh Poyarekar 70cc4d3
-			    idx2now = ~0ul;
Siddhesh Poyarekar 70cc4d3
-			    break;
Siddhesh Poyarekar 70cc4d3
-			  }
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-		    else
Siddhesh Poyarekar 70cc4d3
-		      idx2now = --backw2;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-		else
Siddhesh Poyarekar 70cc4d3
-		  {
Siddhesh Poyarekar 70cc4d3
-		    backw2_stop = idx2cnt;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    while (idx2cnt < idx2max)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			if ((rulesets[rule2arr[idx2cnt] * nrules + pass]
Siddhesh Poyarekar 70cc4d3
-			     & sort_backward) == 0)
Siddhesh Poyarekar 70cc4d3
-			  /* No more backward characters to push.  */
Siddhesh Poyarekar 70cc4d3
-			  break;
Siddhesh Poyarekar 70cc4d3
-			++idx2cnt;
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-		    if (backw2_stop == idx2cnt)
Siddhesh Poyarekar 70cc4d3
-		      {
Siddhesh Poyarekar 70cc4d3
-			/* No sequence at all or just one.  */
Siddhesh Poyarekar 70cc4d3
-			if (idx2cnt == idx2max)
Siddhesh Poyarekar 70cc4d3
-			  /* Note that seq2len is still zero.  */
Siddhesh Poyarekar 70cc4d3
-			  break;
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-			backw2_stop = ~0ul;
Siddhesh Poyarekar 70cc4d3
-			idx2now = idx2cnt++;
Siddhesh Poyarekar 70cc4d3
-		      }
Siddhesh Poyarekar 70cc4d3
-		    else
Siddhesh Poyarekar 70cc4d3
-		      /* We pushed backward sequences.  */
Siddhesh Poyarekar 70cc4d3
-		      idx2now = backw2 = idx2cnt - 1;
Siddhesh Poyarekar 70cc4d3
-		  }
Siddhesh Poyarekar 70cc4d3
-	      }
Siddhesh Poyarekar 70cc4d3
-	    while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
Siddhesh Poyarekar 70cc4d3
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      get_next_seq_nocache (&seq1, nrules, rulesets, weights, table,
Siddhesh Poyarekar 70cc4d3
+				    extra, indirect, pass);
Siddhesh Poyarekar 70cc4d3
+	      get_next_seq_nocache (&seq2, nrules, rulesets, weights, table,
Siddhesh Poyarekar 70cc4d3
+				    extra, indirect, pass);
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else if (pass == 0)
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
Siddhesh Poyarekar 70cc4d3
+			    indirect);
Siddhesh Poyarekar 70cc4d3
+	      get_next_seq (&seq2, nrules, rulesets, weights, table, extra,
Siddhesh Poyarekar 70cc4d3
+			    indirect);
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    {
Siddhesh Poyarekar 70cc4d3
+	      get_next_seq_cached (&seq1, nrules, pass, rulesets, weights);
Siddhesh Poyarekar 70cc4d3
+	      get_next_seq_cached (&seq2, nrules, pass, rulesets, weights);
Siddhesh Poyarekar 70cc4d3
+	    }
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
 	  /* See whether any or both strings are empty.  */
Siddhesh Poyarekar 70cc4d3
-	  if (seq1len == 0 || seq2len == 0)
Siddhesh Poyarekar 70cc4d3
+	  if (seq1.len == 0 || seq2.len == 0)
Siddhesh Poyarekar 70cc4d3
 	    {
Siddhesh Poyarekar 70cc4d3
-	      if (seq1len == seq2len)
Siddhesh Poyarekar 70cc4d3
+	      if (seq1.len == seq2.len)
Siddhesh Poyarekar 70cc4d3
 		/* Both ended.  So far so good, both strings are equal
Siddhesh Poyarekar 70cc4d3
 		   at this level.  */
Siddhesh Poyarekar 70cc4d3
 		break;
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
 	      /* This means one string is shorter than the other.  Find out
Siddhesh Poyarekar 70cc4d3
 		 which one and return an appropriate value.  */
Siddhesh Poyarekar 70cc4d3
-	      result = seq1len == 0 ? -1 : 1;
Siddhesh Poyarekar 70cc4d3
+	      result = seq1.len == 0 ? -1 : 1;
Siddhesh Poyarekar 70cc4d3
 	      goto free_and_return;
Siddhesh Poyarekar 70cc4d3
 	    }
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
-	  /* Test for position if necessary.  */
Siddhesh Poyarekar 70cc4d3
-	  if (position && val1 != val2)
Siddhesh Poyarekar 70cc4d3
-	    {
Siddhesh Poyarekar 70cc4d3
-	      result = val1 - val2;
Siddhesh Poyarekar 70cc4d3
-	      goto free_and_return;
Siddhesh Poyarekar 70cc4d3
-	    }
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	  /* Compare the two sequences.  */
Siddhesh Poyarekar 70cc4d3
-	  do
Siddhesh Poyarekar 70cc4d3
-	    {
Siddhesh Poyarekar 70cc4d3
-	      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
Siddhesh Poyarekar 70cc4d3
-		{
Siddhesh Poyarekar 70cc4d3
-		  /* The sequences differ.  */
Siddhesh Poyarekar 70cc4d3
-		  result = (weights[idx1arr[idx1now]]
Siddhesh Poyarekar 70cc4d3
-			    - weights[idx2arr[idx2now]]);
Siddhesh Poyarekar 70cc4d3
-		  goto free_and_return;
Siddhesh Poyarekar 70cc4d3
-		}
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	      /* Increment the offsets.  */
Siddhesh Poyarekar 70cc4d3
-	      ++idx1arr[idx1now];
Siddhesh Poyarekar 70cc4d3
-	      ++idx2arr[idx2now];
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	      --seq1len;
Siddhesh Poyarekar 70cc4d3
-	      --seq2len;
Siddhesh Poyarekar 70cc4d3
-	    }
Siddhesh Poyarekar 70cc4d3
-	  while (seq1len > 0 && seq2len > 0);
Siddhesh Poyarekar 70cc4d3
-
Siddhesh Poyarekar 70cc4d3
-	  if (position && seq1len != seq2len)
Siddhesh Poyarekar 70cc4d3
-	    {
Siddhesh Poyarekar 70cc4d3
-	      result = seq1len - seq2len;
Siddhesh Poyarekar 70cc4d3
-	      goto free_and_return;
Siddhesh Poyarekar 70cc4d3
-	    }
Siddhesh Poyarekar 70cc4d3
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
Siddhesh Poyarekar 70cc4d3
+	    result = do_compare_nocache (&seq1, &seq2, position, weights);
Siddhesh Poyarekar 70cc4d3
+	  else
Siddhesh Poyarekar 70cc4d3
+	    result = do_compare (&seq1, &seq2, position, weights);
Siddhesh Poyarekar 70cc4d3
+	  if (result != 0)
Siddhesh Poyarekar 70cc4d3
+	    goto free_and_return;
Siddhesh Poyarekar 70cc4d3
 	}
Siddhesh Poyarekar 70cc4d3
+
Siddhesh Poyarekar 70cc4d3
+      if (__glibc_likely (seq1.rulearr != NULL))
Siddhesh Poyarekar 70cc4d3
+	rule = seq1.rulearr[0];
Siddhesh Poyarekar 70cc4d3
+      else
Siddhesh Poyarekar 70cc4d3
+	rule = seq1.rule;
Siddhesh Poyarekar 70cc4d3
     }
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
   /* Free the memory if needed.  */
Siddhesh Poyarekar 70cc4d3
  free_and_return:
Siddhesh Poyarekar 70cc4d3
   if (use_malloc)
Siddhesh Poyarekar 70cc4d3
-    free (idx1arr);
Siddhesh Poyarekar 70cc4d3
+    free (seq1.idxarr);
Siddhesh Poyarekar 70cc4d3
 
Siddhesh Poyarekar 70cc4d3
   return result;
Siddhesh Poyarekar 70cc4d3
 }