about summary refs log tree commit diff
path: root/locale
diff options
context:
space:
mode:
Diffstat (limited to 'locale')
-rw-r--r--locale/programs/ld-collate.c66
1 files changed, 40 insertions, 26 deletions
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index bd07f70612..226bf23b4a 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -112,6 +112,7 @@ struct element_t
 
   /* Next element in wide character output list.  */
   struct element_t *wcnext;
+  struct element_t *wclast;
 };
 
 /* Special element value.  */
@@ -1669,6 +1670,7 @@ Computing table size for collation table might take a while..."),
       if (runp->wcs != NULL)
 	{
 	  struct element_t **eptr;
+	  struct element_t *lastp = NULL;
 	  size_t idx;
 
 	  /* Find a free index.  */
@@ -1712,11 +1714,15 @@ Computing table size for collation table might take a while..."),
 		}
 
 	      /* To the next entry.  */
+	      lastp = *eptr;
 	      eptr = &(*eptr)->wcnext;
 	    }
 
 	  /* Set the pointers.  */
 	  runp->wcnext = *eptr;
+	  runp->wclast = lastp;
+	  if (*eptr != NULL)
+	    (*eptr)->wclast = runp;
 	  *eptr = runp;
 	dont_insertwc:
 	}
@@ -2286,19 +2292,18 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 	    int32_t weightidx;
 	    int added;
 
-	    /* Output the weight info.  */
-	    weightidx = output_weightwc (&weightpool, collate, runp);
-
 	    /* Find out wether this is a single entry or we have more than
 	       one consecutive entry.  */
 	    if (runp->wcnext != NULL
 		&& runp->nwcs == runp->wcnext->nwcs
 		&& wmemcmp ((wchar_t *) runp->wcs,
 			    (wchar_t *)runp->wcnext->wcs, runp->nwcs - 1) == 0
-		&& (runp->wcs[runp->nwcs - 1] + 1
-		    == runp->wcnext->wcs[runp->nwcs - 1]))
+		&& (runp->wcs[runp->nwcs - 1]
+		    == runp->wcnext->wcs[runp->nwcs - 1] + 1))
 	      {
 		int i;
+		struct element_t *series_startp = runp;
+		struct element_t *curp;
 
 		/* Now add first the initial byte sequence.  */
 		added = (1 + 1 + 2 * (runp->nwcs - 1)) * sizeof (int32_t);
@@ -2322,34 +2327,46 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 		    i = runp->nwcs - 1;
 		    obstack_grow (&extrapool, &i, sizeof (int32_t));
 		  }
+
+		do
+		  runp = runp->wcnext;
+		while (runp->wcnext != NULL
+		       && runp->nwcs == runp->wcnext->nwcs
+		       && wmemcmp ((wchar_t *) runp->wcs,
+				   (wchar_t *)runp->wcnext->wcs,
+				   runp->nwcs - 1) == 0
+		       && (runp->wcs[runp->nwcs - 1]
+			   == runp->wcnext->wcs[runp->nwcs - 1] + 1));
+
+		/* Now walk backward from here to the beginning.  */
+		curp = runp;
+
 		for (i = 1; i < runp->nwcs; ++i)
 		  if (sizeof (int32_t) == sizeof (int))
-		    obstack_int_grow_fast (&extrapool, runp->wcs[i]);
+		    obstack_int_grow_fast (&extrapool, curp->wcs[i]);
 		  else
-		    obstack_grow (&extrapool, &runp->wcs[i], sizeof (int32_t));
+		    obstack_grow (&extrapool, &curp->wcs[i], sizeof (int32_t));
 
 		/* Now find the end of the consecutive sequence and
                    add all the indeces in the indirect pool.  */
-		while (1)
+		do
 		  {
+		    weightidx = output_weightwc (&weightpool, collate, curp);
 		    if (sizeof (int32_t) == sizeof (int))
 		      obstack_int_grow (&extrapool, weightidx);
 		    else
 		      obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
 
-		    runp = runp->next;
-		    if (runp->wcnext == NULL
-			|| runp->nwcs != runp->wcnext->nwcs
-			|| wmemcmp ((wchar_t *) runp->wcs,
-				    (wchar_t *) runp->wcnext->wcs,
-				    runp->nwcs - 1) != 0
-			|| (runp->wcs[runp->nwcs - 1] + 1
-			    != runp->wcnext->wcs[runp->nwcs - 1]))
-		      break;
-
-		    /* Insert the weight.  */
-		    weightidx = output_weightwc (&weightpool, collate, runp);
+		    curp = curp->wclast;
 		  }
+		while (curp != series_startp);
+
+		/* Add the final weight.  */
+		weightidx = output_weightwc (&weightpool, collate, curp);
+		if (sizeof (int32_t) == sizeof (int))
+		  obstack_int_grow (&indirectpool, weightidx);
+		else
+		  obstack_grow (&indirectpool, &weightidx, sizeof (int32_t));
 
 		/* And add the end byte sequence.  Without length this
                    time.  */
@@ -2358,12 +2375,6 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 		    obstack_int_grow (&extrapool, runp->wcs[i]);
 		  else
 		    obstack_grow (&extrapool, &runp->wcs[i], sizeof (int32_t));
-
-		weightidx = output_weightwc (&weightpool, collate, runp);
-		if (sizeof (int32_t) == sizeof (int))
-		  obstack_int_grow (&extrapool, weightidx);
-		else
-		  obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
 	      }
 	    else
 	      {
@@ -2372,6 +2383,9 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 		   tested for).  */
 		int i;
 
+		/* Output the weight info.  */
+		weightidx = output_weightwc (&weightpool, collate, runp);
+
 		added = (1 + 1 + runp->nwcs - 1) * sizeof (int32_t);
 		if (sizeof (int) == sizeof (int32_t))
 		  obstack_make_room (&extrapool, added);