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