buf, lenfrom);
buf, lenfrom, 1);
handle_ellipsis (struct linereader *ldfile, struct token *arg,		 enum token_t ellipsis, struct charmap_t *charmap,		 struct repertoire_t *repertoire,		 struct locale_collate_t *collate){  struct element_t *startp;  struct element_t *endp;  /* Unlink the entry added for the ellipsis.  */  unlink_element (collate);  startp = collate->cursor;  /* Process and add the end-entry.  */  if (arg != NULL      && insert_value (ldfile, arg, charmap, repertoire, collate))    /* Something went wrong with inserting the to-value.  This means       we cannot process the ellipsis.  */    return;  /* Reset the cursor.  */  collate->cursor = startp;  /* Now we have to handle many different situations:     - we have to distinguish between the three different ellipsis forms     - the is the ellipsis at the beginning, in the middle, or at the end.  */  endp = collate->cursor->next;  assert (arg == NULL || endp != NULL);  /* Both, the start and the end symbol, must stand for characters.  */  if ((startp == NULL || startp->name == NULL)      || (endp == NULL || endp->name == NULL))    {      lr_error (ldfile, _("\%s: the start end the end symbol of a range must stand for characters"),		"LC_COLLATE");      return;    }  if (ellipsis == tok_ellipsis3)    {      /* One requirement we make here: the length of the byte	 sequences for the first and end character must be the same.	 This is mainly to prevent unwanted effects and this is often	 not what is wanted.  */      size_t len = (startp->mbs != NULL ? startp->nmbs		    : (endp->mbs != NULL ? endp->nmbs : 0));      char mbcnt[len + 1];      char mbend[len + 1];      /* Well, this should be caught somewhere else already.  Just to	 make sure.  */      assert (startp == NULL || startp->wcs == NULL || startp->wcs[1] == 0);      assert (endp == NULL || endp->wcs == NULL || endp->wcs[1] == 0);      if (startp != NULL && endp != NULL	  && startp->mbs != NULL && endp->mbs != NULL	  && startp->nmbs != endp->nmbs)	{	  lr_error (ldfile, _("\%s: byte sequences of first and last character must have the same length"),		    "LC_COLLATE");	  return;	}      /* Determine whether we have to generate multibyte sequences.  */      if ((startp == NULL || startp->mbs != NULL)	  && (endp == NULL || endp->mbs != NULL))	{	  int cnt;	  int ret;	  /* Prepare the beginning byte sequence.  This is either from the	     beginning byte sequence or it is all nulls if it was an	     initial ellipsis.  */	  if (startp == NULL || startp->mbs == NULL)	    memset (mbcnt, '\0', len);	  else	    {	      memcpy (mbcnt, startp->mbs, len);	      /* And increment it so that the value is the first one we will		 try to insert.  */	      for (cnt = len - 1; cnt >= 0; --cnt)		if (++mbcnt[cnt] != '\0')		  break;	    }	  mbcnt[len] = '\0';	  /* And the end sequence.  */	  if (endp == NULL || endp->mbs == NULL)	    memset (mbend, '\0', len);	  else	    memcpy (mbend, endp->mbs, len);	  mbend[len] = '\0';	  /* Test whether we have a correct range.  */	  ret = memcmp (mbcnt, mbend, len);	  if (ret >= 0)	    {	      if (ret > 0)		lr_error (ldfile, _("%s: byte sequence of first character of \sequence is not lower than that of the last character"), "LC_COLLATE");	      return;	    }	  /* Generate the byte sequences data.  */	  while (1)	    {	      struct charseq *seq;	      /* Quite a bit of work ahead.  We have to find the character		 definition for the byte sequence and then determine the		 wide character belonging to it.  */	      seq = charmap_find_symbol (charmap, mbcnt, len);	      if (seq != NULL)		{		  struct element_t *elem;		  size_t namelen;		  if (seq->ucs4 == UNINITIALIZED_CHAR_VALUE)		    seq->ucs4 = repertoire_find_value (repertoire, seq->name,						       strlen (seq->name));		  /* I don't this this can ever happen.  */		  assert (seq->name != NULL);		  namelen = strlen (seq->name);		  /* Now we are ready to insert the new value in the		     sequence.  Find out whether the element is		     already known.  */		  if (find_entry (&collate->seq_table, seq->name, namelen,				  (void **) &elem) != 0)		    {		      uint32_t wcs[2] = { seq->ucs4, 0 };		      /* We have to allocate an entry.  */		      elem = new_element (collate, mbcnt, len, wcs, seq->name,					  namelen);		      /* And add it to the table.  */		      if (insert_entry (&collate->seq_table, seq->name,					namelen, elem) != 0)			/* This cannot happen.  */			assert (! "Internal error");		    }		  /* Test whether this element is not already in the list.  */		  if (elem->next != NULL || (collate->cursor != NULL					     && elem->next == collate->cursor))		    {		      lr_error (ldfile, _("\order for `%.*s' already defined at %s:%zu"),				(int) namelen, seq->name,				elem->file, elem->line);		      goto increment;		    }		  /* Enqueue the new element.  */		  elem->last = collate->cursor;		  if (collate->cursor != NULL)		    elem->next = NULL;		  else		    {		      elem->next = collate->cursor->next;		      elem->last->next = elem;		      if (elem->next != NULL)			elem->next->last = elem;		    }		  if (collate->start == NULL)		    {		      assert (collate->cursor == NULL);		      collate->start = elem;		    }		  collate->cursor = elem;		 /* Add the weight value.  We take them from the		    `ellipsis_weights' member of `collate'.  */		  elem->weights = (struct element_list_t *)		    obstack_alloc (&collate->mempool,				   nrules * sizeof (struct element_list_t));		  for (cnt = 0; cnt < nrules; ++cnt)		    if (collate->ellipsis_weight.weights[cnt].cnt == 1			&& (collate->ellipsis_weight.weights[cnt].w[0]			    == ELEMENT_ELLIPSIS2))		      {			elem->weights[cnt].w = (struct element_t **)			  obstack_alloc (&collate->mempool,					 sizeof (struct element_t *));			elem->weights[cnt].w[0] = elem;			elem->weights[cnt].cnt = 1;		      }		    else		      {			/* Simly use the weight from `ellipsis_weight'.  */			elem->weights[cnt].w =			  collate->ellipsis_weight.weights[cnt].w;			elem->weights[cnt].cnt =			  collate->ellipsis_weight.weights[cnt].cnt;		      }		}	      /* Increment for the next round.  */	    increment:	      for (cnt = len - 1; cnt >= 0; --cnt)		if (++mbcnt[cnt] != '\0')		  break;	      /* Find out whether this was all.  */	      if (cnt < 0 || memcmp (mbcnt, mbend, len) >= 0)		/* Yep, that's all.  */		break;	    }	}    }  else    {      /* For symbolic range we naturally must have a beginning and an	 end specified by the user.  */      if (startp == NULL)	lr_error (ldfile, _("\%s: symbolic range ellipsis must not directly follow `order_start'"),		  "LC_COLLATE");      else if (endp == NULL)	lr_error (ldfile, _("\%s: symbolic range ellipsis must not be direct followed by `order_end'"),		  "LC_COLLATE");      else	{	  /* Determine the range.  To do so we have to determine the             common prefix of the both names and then the numeric             values of both ends.  */	  size_t lenfrom = strlen (startp->name);	  size_t lento = strlen (endp->name);	  char buf[lento + 1];	  int preflen = 0;	  long int from;	  long int to;	  char *cp;	  int base = ellipsis == tok_ellipsis2 ? 16 : 10;	  if (lenfrom != lento)	    {	    invalid_range:	      lr_error (ldfile, _("\`%s' and `%.*s' are no valid names for symbolic range"),			startp->name, (int) lento, endp->name);	      return;	    }	  while (startp->name[preflen] == endp->name[preflen])	    if (startp->name[preflen] == '\0')	      /* Nothing to be done.  The start and end point are identical		 and while inserting the end point we have already given		 the user an error message.  */	      return;	    else	      ++preflen;	  errno = 0;	  from = strtol (startp->name + preflen, &cp, base);	  if ((from == UINT_MAX && errno == ERANGE) || *cp != '\0')	    goto invalid_range;	  errno = 0;	  to = strtol (endp->name + preflen, &cp, base);	  if ((to == UINT_MAX && errno == ERANGE) || *cp != '\0')	    goto invalid_range;	  /* Copy the prefix.  */	  memcpy (buf, startp->name, preflen);	  /* Loop over all values.  */	  for (++from; from < to; ++from)	    {	      struct element_t *elem = NULL;	      struct charseq *seq;	      uint32_t wc;	      int cnt;	      /* Generate the the name.  */	      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 (elem->next != NULL || (collate->cursor != NULL					     && elem->next == collate->cursor))		    {		      lr_error (ldfile, _("\%s: order for `%.*s' already defined at %s:%zu"),				"LC_COLLATE", (int) lenfrom, buf,				elem->file, elem->line);		      continue;		    }		  if (elem->name == NULL)		    {		      lr_error (ldfile, _("%s: `%s' must be a charater"),				"LC_COLLATE", buf);		      continue;		    }		}	      if (elem == NULL || (elem->mbs == NULL && elem->wcs == NULL))		{		  /* Search for a character of this name.  */		  seq = charmap_find_value (charmap, buf, lenfrom);		  if (seq == NULL || seq->ucs4 == UNINITIALIZED_CHAR_VALUE)		    {		      wc = repertoire_find_value (repertoire, buf, lenfrom);		      if (seq != NULL)			seq->ucs4 = wc;		    }		  else		    wc = seq->ucs4;		  if (wc == ILLEGAL_CHAR_VALUE && seq == NULL)		    /* We don't know anything about a character with this		       name.  XXX Should we warn?  */		    continue;		  if (elem == NULL)		    {		      uint32_t wcs[2] = { wc, 0 };		      /* We have to allocate an entry.  */		      elem = new_element (collate,					  seq != NULL ? seq->bytes : NULL,					  seq != NULL ? seq->nbytes : 0,					  wc == ILLEGAL_CHAR_VALUE					  ? NULL : wcs,					  buf, lenfrom);		    }		  else		    {		      /* Update the element.  */		      if (seq != NULL)			{			  elem->mbs = obstack_copy0 (&collate->mempool,						     seq->bytes, seq->nbytes);			  elem->nmbs = seq->nbytes;			}		      if (wc != ILLEGAL_CHAR_VALUE)			{			  uint32_t zero = 0;			  obstack_grow (&collate->mempool,					&wc, sizeof (uint32_t));			  obstack_grow (&collate->mempool,					&zero, sizeof (uint32_t));			  elem->wcs = obstack_finish (&collate->mempool);			  elem->nwcs = 1;			}		    }		  elem->file = ldfile->fname;		  elem->line = ldfile->lineno;		  elem->section = collate->current_section;		}	      /* Enqueue the new element.  */	      elem->last = collate->cursor;	      elem->next = collate->cursor->next;	      elem->last->next = elem;	      if (elem->next != NULL)		elem->next->last = elem;	      collate->cursor = elem;	      /* Now add the weights.  They come from the `ellipsis_weights'		 member of `collate'.  */	      elem->weights = (struct element_list_t *)		obstack_alloc (&collate->mempool,			       nrules * sizeof (struct element_list_t));	      for (cnt = 0; cnt < nrules; ++cnt)		if (collate->ellipsis_weight.weights[cnt].cnt == 1		    && (collate->ellipsis_weight.weights[cnt].w[0]			== ELEMENT_ELLIPSIS2))		  {		    elem->weights[cnt].w = (struct element_t **)		      obstack_alloc (&collate->mempool,				     sizeof (struct element_t *));		    elem->weights[cnt].w[0] = elem;		    elem->weights[cnt].cnt = 1;		  }		else		  {		    /* Simly use the weight from `ellipsis_weight'.  */		    elem->weights[cnt].w =		      collate->ellipsis_weight.weights[cnt].w;		    elem->weights[cnt].cnt =		      collate->ellipsis_weight.weights[cnt].cnt;		  }	    }	}    }}