about summary refs log tree commit diff
path: root/locale/programs/ld-collate.c
diff options
context:
space:
mode:
Diffstat (limited to 'locale/programs/ld-collate.c')
-rw-r--r--locale/programs/ld-collate.c121
1 files changed, 76 insertions, 45 deletions
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index 65229275ff..c629bd477a 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -137,9 +137,6 @@ struct locale_collate_t
   /* To make handling of errors easier we have another section.  */
   struct section_list error_section;
 
-  /* Number of sorting rules given in order_start line.  */
-  uint32_t nrules;
-
   /* Start of the order list.  */
   struct element_t *start;
 
@@ -176,7 +173,7 @@ struct locale_collate_t
 
 /* We have a few global variables which are used for reading all
    LC_COLLATE category descriptions in all files.  */
-static int nrules;
+static uint32_t nrules;
 
 
 /* These are definitions used by some of the functions for handling
@@ -426,7 +423,7 @@ read_directions (struct linereader *ldfile, struct token *arg,
 	      if (! warned)
 		{
 		  lr_error (ldfile, _("\
-%s: `%s' mentioned twice in definition of weight %d in category `%s'"),
+%s: `%s' mentioned twice in definition of weight %d"),
 			    "LC_COLLATE", "position", cnt + 1);
 		}
 	    }
@@ -450,7 +447,13 @@ read_directions (struct linereader *ldfile, struct token *arg,
 
 	  /* See whether we have to increment the counter.  */
 	  if (arg->tok != tok_comma && rules[cnt] != 0)
-	    ++cnt;
+	    {
+	      /* Add the default `forward' if we have seen only `position'.  */
+	      if (rules[cnt] == sort_position)
+		rules[cnt] = sort_position | sort_forward;
+
+	      ++cnt;
+	    }
 
 	  if (arg->tok == tok_eof || arg->tok == tok_eol)
 	    /* End of line or file, so we exit the loop.  */
@@ -876,7 +879,7 @@ insert_value (struct linereader *ldfile, struct token *arg,
 	      elem->nmbs = seq->nbytes;
 	    }
 
-	  if (elem->wcs == NULL && seq != ILLEGAL_CHAR_VALUE)
+	  if (elem->wcs == NULL && wc != ILLEGAL_CHAR_VALUE)
 	    {
 	      uint32_t wcs[2] = { wc, 0 };
 
@@ -1552,7 +1555,7 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
 }
 
 
-static inline int32_t
+static int32_t
 output_weight (struct obstack *pool, struct locale_collate_t *collate,
 	       struct element_t *elem)
 {
@@ -1575,25 +1578,18 @@ output_weight (struct obstack *pool, struct locale_collate_t *collate,
       int len = 0;
       int i;
 
-      /* Add the direction.  */
-      obstack_1grow (pool, elem->section->rules[cnt]);
-
       for (i = 0; i < elem->weights[cnt].cnt; ++i)
-	/* Encode the weight value.  */
-	if (elem->weights[cnt].w[i] == NULL)
-	  {
-	    /* This entry was IGNORE.  */
-	    buf[len++] = IGNORE_CHAR;
-	  }
-	else
+	/* Encode the weight value.  We do nothing for IGNORE entries.  */
+	if (elem->weights[cnt].w[i] != NULL)
 	  len += utf8_encode (&buf[len],
 			      elem->weights[cnt].w[i]->mborder[cnt]);
 
       /* And add the buffer content.  */
+      obstack_1grow (pool, len);
       obstack_grow (pool, buf, len);
     }
 
-  return retval;
+  return retval | ((elem->section->ruleidx & 0x7f) << 24);
 }
 
 
@@ -1611,11 +1607,13 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
   int32_t tablemb[256];
   struct obstack weightpool;
   struct obstack extrapool;
+  struct obstack indirectpool;
   struct section_list *sect;
   int i;
 
   obstack_init (&weightpool);
   obstack_init (&extrapool);
+  obstack_init (&indirectpool);
 
   data.magic = LIMAGIC (LC_COLLATE);
   data.n = nelems;
@@ -1629,7 +1627,7 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
   cnt = 0;
 
   assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_NRULES));
-  iov[2 + cnt].iov_base = &collate->nrules;
+  iov[2 + cnt].iov_base = &nrules;
   iov[2 + cnt].iov_len = sizeof (uint32_t);
   idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
   ++cnt;
@@ -1638,7 +1636,12 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
   for (sect = collate->sections, i = 0; sect != NULL; sect = sect->next)
     if (sect->ruleidx == i)
       {
-	obstack_grow (&weightpool, sect->rules, nrules);
+	int j;
+
+	obstack_make_room (&weightpool, nrules);
+
+	for (j = 0; j < nrules; ++j)
+	  obstack_1grow_fast (&weightpool, sect->rules[j]);
 	++i;
       }
   /* And align the output.  */
@@ -1674,7 +1677,7 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 	&& collate->mbheads[ch]->nmbs == 1)
       {
 	tablemb[ch] = output_weight (&weightpool, collate,
-				      collate->mbheads[ch]);
+				     collate->mbheads[ch]);
       }
     else
       {
@@ -1719,38 +1722,60 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 	      {
 		int i;
 
-		/* More than one consecutive entry.  We mark this by having
-		   a negative index into the weight table.  */
-		weightidx = -weightidx;
-
 		/* Now add first the initial byte sequence.  */
 		added = ((sizeof (int32_t) + 1 + 1 + 2 * (runp->nmbs - 1)
 			  + __alignof__ (int32_t) - 1)
 			 & ~(__alignof__ (int32_t) - 1));
 		obstack_make_room (&extrapool, added);
 
+		/* More than one consecutive entry.  We mark this by having
+		   a negative index into the indirect table.  */
 		if (sizeof (int32_t) == sizeof (int))
-		  obstack_int_grow_fast (&extrapool, weightidx);
+		  obstack_int_grow_fast (&extrapool,
+					 obstack_object_size (&indirectpool)
+					 / sizeof (int32_t));
 		else
-		  obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
-		obstack_1grow_fast (&extrapool, runp->section->ruleidx);
+		  {
+		    int32_t i = (obstack_object_size (&indirectpool)
+				 / sizeof (int32_t));
+		    obstack_grow (&extrapool, &i, sizeof (int32_t));
+		  }
 		obstack_1grow_fast (&extrapool, runp->nmbs - 1);
 		for (i = 1; i < runp->nmbs; ++i)
 		  obstack_1grow_fast (&extrapool, runp->mbs[i]);
 
-		/* Now find the end of the consecutive sequence.  */
-		do
-		  runp = runp->next;
-		while (runp->mbnext != NULL
-		       && runp->nmbs == runp->mbnext->nmbs
-		       && memcmp (runp->mbs, runp->mbnext->mbs,
-				  runp->nmbs - 1) == 0
-		       && (runp->mbs[runp->nmbs - 1] + 1
-			   == runp->mbnext->mbs[runp->nmbs - 1]));
-
-		/* And add the end by sequence.  Without length this time.  */
+		/* Now find the end of the consecutive sequence and
+                   add all the indeces in the indirect pool.  */
+		while (1)
+		  {
+		    if (sizeof (int32_t) == sizeof (int))
+		      obstack_int_grow_fast (&extrapool, weightidx);
+		    else
+		      obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
+
+		    runp = runp->next;
+		    if (runp->mbnext == NULL
+			|| runp->nmbs != runp->mbnext->nmbs
+			|| memcmp (runp->mbs, runp->mbnext->mbs,
+				   runp->nmbs - 1) != 0
+			|| (runp->mbs[runp->nmbs - 1] + 1
+			    != runp->mbnext->mbs[runp->nmbs - 1]))
+		      break;
+
+		    /* Insert the weight.  */
+		    weightidx = output_weight (&weightpool, collate, runp);
+		  }
+
+		/* And add the end byte sequence.  Without length this
+                   time.  */
 		for (i = 1; i < runp->nmbs; ++i)
 		  obstack_1grow_fast (&extrapool, runp->mbs[i]);
+
+		weightidx = output_weight (&weightpool, collate, runp);
+		if (sizeof (int32_t) == sizeof (int))
+		  obstack_int_grow_fast (&extrapool, weightidx);
+		else
+		  obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
 	      }
 	    else
 	      {
@@ -1768,7 +1793,6 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 		  obstack_int_grow_fast (&extrapool, weightidx);
 		else
 		  obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
-		obstack_1grow_fast (&extrapool, runp->section->ruleidx);
 		obstack_1grow_fast (&extrapool, runp->nmbs - 1);
 		for (i = 1; i < runp->nmbs; ++i)
 		  obstack_1grow_fast (&extrapool, runp->mbs[i]);
@@ -1835,6 +1859,12 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
   idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
   ++cnt;
 
+  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_INDIRECTMB));
+  iov[2 + cnt].iov_len = obstack_object_size (&indirectpool);
+  iov[2 + cnt].iov_base = obstack_finish (&indirectpool);
+  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
+  ++cnt;
+
 
   assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));
 
@@ -1842,6 +1872,7 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
 
   obstack_free (&weightpool, NULL);
   obstack_free (&extrapool, NULL);
+  obstack_free (&indirectpool, NULL);
 }
 
 
@@ -2291,16 +2322,16 @@ error while adding equivalent collating symbol"));
 		      uint32_t cnt;
 
 		      /* This means we have exactly one rule: `forward'.  */
-		      if (collate->nrules > 1)
+		      if (nrules > 1)
 			lr_error (ldfile, _("\
 %s: invalid number of sorting rules"),
 				  "LC_COLLATE");
 		      else
-			collate->nrules = 1;
+			nrules = 1;
 		      sp->rules = obstack_alloc (&collate->mempool,
 						 (sizeof (enum coll_sort_rule)
-						  * collate->nrules));
-		      for (cnt = 0; cnt < collate->nrules; ++cnt)
+						  * nrules));
+		      for (cnt = 0; cnt < nrules; ++cnt)
 			sp->rules[cnt] = sort_forward;
 
 		      /* Next line.  */