elem->weights = (struct element_list_t *) obstack_alloc (&collate->mempool, nrules * sizeof (struct element_list_t)); memset (elem->weights, '\0', nrules * sizeof (struct element_list_t));
elem->section = collate->current_section;
insert_weights (struct linereader *ldfile, struct element_t *elem,		struct charmap_t *charmap, struct repertoire_t *repertoire,		struct locale_collate_t *collate, enum token_t ellipsis){  int weight_cnt;  struct token *arg;  /* Initialize all the fields.  */  elem->file = ldfile->fname;  elem->line = ldfile->lineno;  elem->last = collate->cursor;  elem->next = collate->cursor ? collate->cursor->next : NULL;  if (collate->cursor != NULL && collate->cursor->next != NULL)    collate->cursor->next->last = elem;  elem->section = collate->current_section;  if (collate->cursor != NULL)    collate->cursor->next = elem;  if (collate->start == NULL)    {      assert (collate->cursor == NULL);      collate->start = elem;    }  elem->weights = (struct element_list_t *)    obstack_alloc (&collate->mempool, nrules * sizeof (struct element_list_t));  memset (elem->weights, '\0', nrules * sizeof (struct element_list_t));  if (collate->current_section->first == NULL)    collate->current_section->first = elem;  if (collate->current_section->last == collate->cursor)    collate->current_section->last = elem;  collate->cursor = elem;  weight_cnt = 0;  arg = lr_token (ldfile, charmap, repertoire);  do    {      if (arg->tok == tok_eof || arg->tok == tok_eol)	break;      if (arg->tok == tok_ignore)	{	  /* The weight for this level has to be ignored.  We use the	     null pointer to indicate this.  */	  elem->weights[weight_cnt].w = (struct element_t **)	    obstack_alloc (&collate->mempool, sizeof (struct element_t *));	  elem->weights[weight_cnt].w[0] = NULL;	  elem->weights[weight_cnt].cnt = 1;	}      else if (arg->tok == tok_bsymbol || arg->tok == tok_ucs4)	{	  char ucs4str[10];	  struct element_t *val;	  char *symstr;	  size_t symlen;	  if (arg->tok == tok_bsymbol)	    {	      symstr = arg->val.str.startmb;	      symlen = arg->val.str.lenmb;	    }	  else	    {	      snprintf (ucs4str, sizeof (ucs4str), "U%08X", arg->val.ucs4);	      symstr = ucs4str;	      symlen = 9;	    }	  val = find_element (ldfile, collate, symstr, symlen);	  if (val == NULL)	    break;	  elem->weights[weight_cnt].w = (struct element_t **)	    obstack_alloc (&collate->mempool, sizeof (struct element_t *));	  elem->weights[weight_cnt].w[0] = val;	  elem->weights[weight_cnt].cnt = 1;	}      else if (arg->tok == tok_string)	{	  /* Split the string up in the individual characters and put	     the element definitions in the list.  */	  const char *cp = arg->val.str.startmb;	  int cnt = 0;	  struct element_t *charelem;	  struct element_t **weights = NULL;	  int max = 0;	  if (*cp == '\0')	    {	      lr_error (ldfile, _("%s: empty weight string not allowed"),			"LC_COLLATE");	      lr_ignore_rest (ldfile, 0);	      break;	    }	  do	    {	      if (*cp == '<')		{		  /* Ahh, it's a bsymbol or an UCS4 value.  If it's                     the latter we have to unify the name.  */		  const char *startp = ++cp;		  size_t len;		  while (*cp != '>')		    {		      if (*cp == ldfile->escape_char)			++cp;		      if (*cp == '\0')			/* It's a syntax error.  */			goto syntax;		      ++cp;		    }		  if (cp - startp == 5 && startp[0] == 'U'		      && isxdigit (startp[1]) && isxdigit (startp[2])		      && isxdigit (startp[3]) && isxdigit (startp[4]))		    {		      unsigned int ucs4 = strtoul (startp + 1, NULL, 16);		      char *newstr;		      newstr = (char *) xmalloc (10);		      snprintf (newstr, 10, "U%08X", ucs4);		      startp = newstr;		      len = 9;		    }		  else		    len = cp - startp;		  charelem = find_element (ldfile, collate, startp, len);		  ++cp;		}	      else		{		  /* People really shouldn't use characters directly in		     the string.  Especially since it's not really clear		     what this means.  We interpret all characters in the		     string as if that would be bsymbols.  Otherwise we		     would have to match back to bsymbols somehow and this		     is normally not what people normally expect.  */		  charelem = find_element (ldfile, collate, cp++, 1);		}	      if (charelem == NULL)		{		  /* We ignore the rest of the line.  */		  lr_ignore_rest (ldfile, 0);		  break;		}	      /* Add the pointer.  */	      if (cnt >= max)		{		  struct element_t **newp;		  max += 10;		  newp = (struct element_t **)		    alloca (max * sizeof (struct element_t *));		  memcpy (newp, weights, cnt * sizeof (struct element_t *));		  weights = newp;		}	      weights[cnt++] = charelem;	    }	  while (*cp != '\0');	  /* Now store the information.  */	  elem->weights[weight_cnt].w = (struct element_t **)	    obstack_alloc (&collate->mempool,			   cnt * sizeof (struct element_t *));	  memcpy (elem->weights[weight_cnt].w, weights,		  cnt * sizeof (struct element_t *));	  elem->weights[weight_cnt].cnt = cnt;	  /* We don't need the string anymore.  */	  free (arg->val.str.startmb);	}      else if (ellipsis != tok_none	       && (arg->tok == tok_ellipsis2		   || arg->tok == tok_ellipsis3		   || arg->tok == tok_ellipsis4))	{	  /* It must be the same ellipsis as used in the initial column.  */	  if (arg->tok != ellipsis)	    lr_error (ldfile, _("\%s: weights must use the same ellipsis symbol as the name"),		      "LC_COLLATE");	  /* The weight for this level has to be ignored.  We use the	     null pointer to indicate this.  */	  elem->weights[weight_cnt].w = (struct element_t **)	    obstack_alloc (&collate->mempool, sizeof (struct element_t *));	  elem->weights[weight_cnt].w[0] = ELEMENT_ELLIPSIS2;	  elem->weights[weight_cnt].cnt = 1;	}      else	{	syntax:	  /* It's a syntax error.  */	  lr_error (ldfile, _("%s: syntax error"), "LC_COLLATE");	  lr_ignore_rest (ldfile, 0);	  break;	}      arg = lr_token (ldfile, charmap, repertoire);      /* This better should be the end of the line or a semicolon.  */      if (arg->tok == tok_semicolon)	/* OK, ignore this and read the next token.  */	arg = lr_token (ldfile, charmap, repertoire);      else if (arg->tok != tok_eof && arg->tok != tok_eol)	{	  /* It's a syntax error.  */	  lr_error (ldfile, _("%s: syntax error"), "LC_COLLATE");	  lr_ignore_rest (ldfile, 0);	  break;	}    }  while (++weight_cnt < nrules);  if (weight_cnt < nrules)    {      /* This means the rest of the line uses the current element as	 the weight.  */      do	{	  elem->weights[weight_cnt].w = (struct element_t **)	    obstack_alloc (&collate->mempool, sizeof (struct element_t *));	  if (ellipsis == tok_none)	    elem->weights[weight_cnt].w[0] = elem;	  else	    elem->weights[weight_cnt].w[0] = ELEMENT_ELLIPSIS2;	  elem->weights[weight_cnt].cnt = 1;	}      while (++weight_cnt < nrules);    }  else    {      if (arg->tok == tok_ignore || arg->tok == tok_bsymbol)	{	  /* Too many rule values.  */	  lr_error (ldfile, _("%s: too many values"), "LC_COLLATE");	  lr_ignore_rest (ldfile, 0);	}      else	lr_ignore_rest (ldfile, arg->tok != tok_eol && arg->tok != tok_eof);    }}