about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--locale/programs/ld-collate.c89
1 files changed, 52 insertions, 37 deletions
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index 7aa51c31db..3260c43a9e 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -839,7 +839,7 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
 
 
 static int
-insert_value (struct linereader *ldfile, struct token *arg,
+insert_value (struct linereader *ldfile, const char *symstr, size_t symlen,
 	      struct charmap_t *charmap, struct repertoire_t *repertoire,
 	      struct locale_collate_t *collate)
 {
@@ -849,13 +849,12 @@ insert_value (struct linereader *ldfile, struct token *arg,
   struct element_t *elem = NULL;
 
   /* Try to find the character in the charmap.  */
-  seq = charmap_find_value (charmap, arg->val.str.startmb, arg->val.str.lenmb);
+  seq = charmap_find_value (charmap, symstr, symlen);
 
   /* Determine the wide character.  */
   if (seq == NULL || seq->ucs4 == UNINITIALIZED_CHAR_VALUE)
     {
-      wc = repertoire_find_value (repertoire, arg->val.str.startmb,
-				  arg->val.str.lenmb);
+      wc = repertoire_find_value (repertoire, symstr, symlen);
       if (seq != NULL)
 	seq->ucs4 = wc;
     }
@@ -868,8 +867,7 @@ insert_value (struct linereader *ldfile, struct token *arg,
 	 symbol list.  */
       void *result;
 
-      if (find_entry (&collate->sym_table, arg->val.str.startmb,
-		      arg->val.str.lenmb, &result) == 0)
+      if (find_entry (&collate->sym_table, symstr, symlen, &result) == 0)
 	{
 	  /* It's a collation symbol.  */
 	  struct symbol_t *sym = (struct symbol_t *) result;
@@ -879,8 +877,8 @@ insert_value (struct linereader *ldfile, struct token *arg,
 	    elem = sym->order = new_element (collate, NULL, 0, NULL, NULL, 0,
 					     0);
 	}
-      else if (find_entry (&collate->elem_table, arg->val.str.startmb,
-			   arg->val.str.lenmb, (void **) &elem) != 0)
+      else if (find_entry (&collate->elem_table, symstr, symlen,
+			   (void **) &elem) != 0)
 	{
 	  /* It's also no collation element.  Therefore ignore it.  */
 	  lr_ignore_rest (ldfile, 0);
@@ -890,8 +888,8 @@ insert_value (struct linereader *ldfile, struct token *arg,
   else
     {
       /* Otherwise the symbols stands for a character.  */
-      if (find_entry (&collate->seq_table, arg->val.str.startmb,
-		      arg->val.str.lenmb, (void **) &elem) != 0)
+      if (find_entry (&collate->seq_table, symstr, symlen,
+		      (void **) &elem) != 0)
 	{
 	  uint32_t wcs[2] = { wc, 0 };
 
@@ -899,11 +897,10 @@ insert_value (struct linereader *ldfile, struct token *arg,
 	  elem = new_element (collate, seq != NULL ? seq->bytes : NULL,
 			      seq != NULL ? seq->nbytes : 0,
 			      wc == ILLEGAL_CHAR_VALUE ? NULL : wcs,
-			      arg->val.str.startmb, arg->val.str.lenmb, 1);
+			      symstr, symlen, 1);
 
 	  /* And add it to the table.  */
-	  if (insert_entry (&collate->seq_table, arg->val.str.startmb,
-			    arg->val.str.lenmb, elem) != 0)
+	  if (insert_entry (&collate->seq_table, symstr, symlen, elem) != 0)
 	    /* This cannot happen.  */
 	    assert (! "Internal error");
 	}
@@ -933,8 +930,7 @@ insert_value (struct linereader *ldfile, struct token *arg,
 			     && elem->next == collate->cursor))
     {
       lr_error (ldfile, _("order for `%.*s' already defined at %s:%Zu"),
-		(int) arg->val.str.lenmb, arg->val.str.startmb,
-		elem->file, elem->line);
+		(int) symlen, symstr, elem->file, elem->line);
       lr_ignore_rest (ldfile, 0);
       return 1;
     }
@@ -946,7 +942,7 @@ insert_value (struct linereader *ldfile, struct token *arg,
 
 
 static void
-handle_ellipsis (struct linereader *ldfile, struct token *arg,
+handle_ellipsis (struct linereader *ldfile, const char *symstr, size_t symlen,
 		 enum token_t ellipsis, struct charmap_t *charmap,
 		 struct repertoire_t *repertoire,
 		 struct locale_collate_t *collate)
@@ -959,8 +955,8 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
   startp = collate->cursor;
 
   /* Process and add the end-entry.  */
-  if (arg != NULL
-      && insert_value (ldfile, arg, charmap, repertoire, collate))
+  if (symstr != NULL
+      && insert_value (ldfile, symstr, symlen, charmap, repertoire, collate))
     /* Something went wrong with inserting the to-value.  This means
        we cannot process the ellipsis.  */
     return;
@@ -973,7 +969,7 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
      - the is the ellipsis at the beginning, in the middle, or at the end.
   */
   endp = collate->cursor->next;
-  assert (arg == NULL || endp != NULL);
+  assert (symstr == NULL || endp != NULL);
 
   /* Both, the start and the end symbol, must stand for characters.  */
   if ((startp != NULL && (startp->name == NULL || ! startp->is_character))
@@ -1232,8 +1228,8 @@ order for `%.*s' already defined at %s:%Zu"),
 	      sprintf (buf + preflen, base == 10 ? "%d" : "%x", from);
 
 	      /* Look whether this name is already defined.  */
-	      if (find_entry (&collate->seq_table, arg->val.str.startmb,
-			      arg->val.str.lenmb, (void **) &elem) == 0)
+	      if (find_entry (&collate->seq_table, symstr, symlen,
+			      (void **) &elem) == 0)
 		{
 		  if (elem->next != NULL || (collate->cursor != NULL
 					     && elem->next == collate->cursor))
@@ -2694,6 +2690,10 @@ collate_read (struct linereader *ldfile, struct localedef_t *result,
 
   while (1)
     {
+      char ucs4buf[10];
+      char *symstr;
+      size_t symlen;
+
       /* Of course we don't proceed beyond the end of file.  */
       if (nowtok == tok_eof)
 	break;
@@ -3196,8 +3196,8 @@ error while adding equivalent collating symbol"));
 	  /* Handle ellipsis at end of list.  */
 	  if (was_ellipsis != tok_none)
 	    {
-	      handle_ellipsis (ldfile, NULL, was_ellipsis, charmap, repertoire,
-			       collate);
+	      handle_ellipsis (ldfile, NULL, 0, was_ellipsis, charmap,
+			       repertoire, collate);
 	      was_ellipsis = tok_none;
 	    }
 
@@ -3223,7 +3223,8 @@ error while adding equivalent collating symbol"));
 	      /* Handle ellipsis at end of list.  */
 	      if (was_ellipsis != tok_none)
 		{
-		  handle_ellipsis (ldfile, arg, was_ellipsis, charmap,
+		  handle_ellipsis (ldfile, arg->val.str.startmb,
+				   arg->val.str.lenmb, was_ellipsis, charmap,
 				   repertoire, collate);
 		  was_ellipsis = tok_none;
 		}
@@ -3293,7 +3294,7 @@ error while adding equivalent collating symbol"));
 	      /* Handle ellipsis at end of list.  */
 	      if (was_ellipsis != tok_none)
 		{
-		  handle_ellipsis (ldfile, NULL, was_ellipsis, charmap,
+		  handle_ellipsis (ldfile, NULL, 0, was_ellipsis, charmap,
 				   repertoire, collate);
 		  was_ellipsis = tok_none;
 		}
@@ -3371,6 +3372,7 @@ error while adding equivalent collating symbol"));
 	  break;
 
 	case tok_bsymbol:
+	case tok_ucs4:
 	  /* Ignore the rest of the line if we don't need the input of
 	     this line.  */
 	  if (ignore_content)
@@ -3379,9 +3381,24 @@ error while adding equivalent collating symbol"));
 	      break;
 	    }
 
-	  if (state != 1 && state != 3)
+	  if (state != 1 && state != 3 && state != 5)
+	    goto err_label;
+
+	  if (state == 5 && nowtok == tok_ucs4)
 	    goto err_label;
 
+	  if (nowtok == tok_ucs4)
+	    {
+	      snprintf (ucs4buf, sizeof (ucs4buf), "U%08X", now->val.ucs4);
+	      symstr = ucs4buf;
+	      symlen = 9;
+	    }
+	  else
+	    {
+	      symstr = arg->val.str.startmb;
+	      symlen = arg->val.str.lenmb;
+	    }
+
 	  if (state == 3)
 	    {
 	      /* It is possible that we already have this collation sequence.
@@ -3396,8 +3413,8 @@ error while adding equivalent collating symbol"));
 		  break;
 		}
 
-	      if (find_entry (&collate->seq_table, arg->val.str.startmb,
-			      arg->val.str.lenmb, (void **) &seqp) == 0)
+	      if (find_entry (&collate->seq_table, symstr, symlen,
+			      (void **) &seqp) == 0)
 		{
 		  /* Remove the entry from the old position.  */
 		  if (seqp->last == NULL)
@@ -3445,9 +3462,8 @@ error while adding equivalent collating symbol"));
 	      while (runp != NULL)
 		{
 		  if (runp->name != NULL
-		      && strlen (runp->name) == arg->val.str.lenmb
-		      && memcmp (runp->name, arg->val.str.startmb,
-				 arg->val.str.lenmb) == 0)
+		      && strlen (runp->name) == symlen
+		      && memcmp (runp->name, symstr, symlen) == 0)
 		    break;
 
 		  prevp = runp;
@@ -3457,8 +3473,7 @@ error while adding equivalent collating symbol"));
 	      if (runp == NULL)
 		{
 		  lr_error (ldfile, _("%s: section `%.*s' not known"),
-			    "LC_COLLATE", (int) arg->val.str.lenmb,
-			    arg->val.str.startmb);
+			    "LC_COLLATE", (int) symlen, symstr);
 		  lr_ignore_rest (ldfile, 0);
 		}
 	      else
@@ -3490,8 +3505,8 @@ error while adding equivalent collating symbol"));
                  the ellipsis now.  */
 	      assert (state == 1);
 
-	      handle_ellipsis (ldfile, arg, was_ellipsis, charmap, repertoire,
-			       collate);
+	      handle_ellipsis (ldfile, symstr, symlen, was_ellipsis, charmap,
+			       repertoire, collate);
 
 	      /* Remember that we processed the ellipsis.  */
 	      was_ellipsis = tok_none;
@@ -3501,7 +3516,7 @@ error while adding equivalent collating symbol"));
 	    }
 
 	  /* Now insert in the new place.  */
-	  insert_value (ldfile, arg, charmap, repertoire, collate);
+	  insert_value (ldfile, symstr, symlen, charmap, repertoire, collate);
 	  break;
 
 	case tok_undefined:
@@ -3579,7 +3594,7 @@ error while adding equivalent collating symbol"));
 		  /* Handle ellipsis at end of list.  */
 		  if (was_ellipsis != tok_none)
 		    {
-		      handle_ellipsis (ldfile, NULL, was_ellipsis, charmap,
+		      handle_ellipsis (ldfile, NULL, 0, was_ellipsis, charmap,
 				       repertoire, collate);
 		      was_ellipsis = tok_none;
 		    }