obstack_int_grow_fast (&extrapool, runp->wcs[i]);
obstack_int_grow_fast (&extrapool, curp->wcs[i]);
collate_output (struct localedef_t *locale, struct charmap_t *charmap,		const char *output_path){  struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;  const size_t nelems = _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE);  struct iovec iov[2 + nelems];  struct locale_file data;  uint32_t idx[nelems];  size_t cnt;  size_t ch;  int32_t tablemb[256];  struct obstack weightpool;  struct obstack extrapool;  struct obstack indirectpool;  struct section_list *sect;  uint32_t *names;  uint32_t *tablewc;  size_t table_size;  uint32_t elem_size;  uint32_t *elem_table;  int i;  struct element_t *runp;  data.magic = LIMAGIC (LC_COLLATE);  data.n = nelems;  iov[0].iov_base = (void *) &data;  iov[0].iov_len = sizeof (data);  iov[1].iov_base = (void *) idx;  iov[1].iov_len = sizeof (idx);  idx[0] = iov[0].iov_len + iov[1].iov_len;  cnt = 0;  assert (cnt == _NL_ITEM_INDEX (_NL_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;  /* If we have no LC_COLLATE data emit only the number of rules as zero.  */  if (collate == NULL)    {      int32_t dummy = 0;      while (cnt < _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE))	{	  /* The words have to be handled specially.  */	  if (cnt == _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE)	      || cnt == _NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS)	      || cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))	    {	      iov[2 + cnt].iov_base = &dummy;	      iov[2 + cnt].iov_len = sizeof (int32_t);	    }	  else	    {	      iov[2 + cnt].iov_base = (char *) "";	      iov[2 + cnt].iov_len = 0;	    }	  if (cnt + 1 < _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE))	    idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;	  ++cnt;	}      assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));      write_locale_data (output_path, "LC_COLLATE", 2 + cnt, iov);      return;    }  obstack_init (&weightpool);  obstack_init (&extrapool);  obstack_init (&indirectpool);  /* Since we are using the sign of an integer to mark indirection the     offsets in the arrays we are indirectly referring to must not be     zero since -0 == 0.  Therefore we add a bit of dummy content.  */  if (sizeof (int) == sizeof (int32_t))    {      obstack_int_grow (&extrapool, 0);      obstack_int_grow (&indirectpool, 0);    }  else    {      int32_t zero = 0;      obstack_grow (&extrapool, &zero, sizeof (zero));      obstack_grow (&indirectpool, &zero, sizeof (zero));    }  /* Prepare the ruleset table.  */  for (sect = collate->sections, i = 0; sect != NULL; sect = sect->next)    if (sect->ruleidx == i)      {	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.  */  i = (nrules * i) % __alignof__ (int32_t);  if (i > 0)    do      obstack_1grow (&weightpool, '\0');    while (++i < __alignof__ (int32_t));  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_RULESETS));  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);  iov[2 + cnt].iov_base = obstack_finish (&weightpool);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  ++cnt;  /* Generate the 8-bit table.  Walk through the lists of sequences     starting with the same byte and add them one after the other to     the table.  In case we have more than one sequence starting with     the same byte we have to use extra indirection.     First add a record for the NUL byte.  This entry will never be used     so it does not matter.  */  tablemb[0] = 0;  /* Now insert the `UNDEFINED' value if it is used.  Since this value     will probably be used more than once it is good to store the     weights only once.  */  if (collate->undefined.used_in_level != 0)    output_weight (&weightpool, collate, &collate->undefined);  for (ch = 1; ch < 256; ++ch)    if (collate->mbheads[ch]->mbnext == NULL	&& collate->mbheads[ch]->nmbs == 1)      {	tablemb[ch] = output_weight (&weightpool, collate,				     collate->mbheads[ch]);      }    else      {	/* The entries in the list are sorted by length and then           alphabetically.  This is the order in which we will add the           elements to the collation table.  This allows to simply           walk the table in sequence and stop at the first matching           entry.  Since the longer sequences are coming first in the           list they have the possibility to match first, just as it           has to be.  In the worst case we are walking to the end of           the list where we put, if no singlebyte sequence is defined           in the locale definition, the weights for UNDEFINED.	   To reduce the length of the search list we compress them a bit.	   This happens by collecting sequences of consecutive byte	   sequences in one entry (having and begin and end byte sequence)	   and add only one index into the weight table.  We can find the	   consecutive entries since they are also consecutive in the list.  */	struct element_t *runp = collate->mbheads[ch];	struct element_t *lastp;	tablemb[ch] = -obstack_object_size (&extrapool);	do	  {	    /* Store the current index in the weight table.  We know that	       the current position in the `extrapool' is aligned on a	       32-bit address.  */	    int32_t weightidx;	    int added;	    /* Find out wether this is a single entry or we have more than	       one consecutive entry.  */	    if (runp->mbnext != NULL		&& runp->nmbs == runp->mbnext->nmbs		&& memcmp (runp->mbs, runp->mbnext->mbs, runp->nmbs - 1) == 0		&& (runp->mbs[runp->nmbs - 1]		    == runp->mbnext->mbs[runp->nmbs - 1] + 1))	      {		int i;		struct element_t *series_startp = runp;		struct element_t *curp;		/* Compute how much space we will need.  */		added = ((sizeof (int32_t) + 1 + 2 * (runp->nmbs - 1)			  + __alignof__ (int32_t) - 1)			 & ~(__alignof__ (int32_t) - 1));		assert ((obstack_object_size (&extrapool)			 & (__alignof__ (int32_t) - 1)) == 0);		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,					 -(obstack_object_size (&indirectpool)					   / sizeof (int32_t)));		else		  {		    int32_t i = -(obstack_object_size (&indirectpool)				  / sizeof (int32_t));		    obstack_grow (&extrapool, &i, sizeof (int32_t));		  }		/* Now search first the end of the series.  */		do		  runp = runp->mbnext;		while (runp->mbnext != NULL		       && runp->nmbs == runp->mbnext->nmbs		       && memcmp (runp->mbs, runp->mbnext->mbs,				  runp->nmbs - 1) == 0		       && (runp->mbs[runp->nmbs - 1]			   == runp->mbnext->mbs[runp->nmbs - 1] + 1));		/* Now walk backward from here to the beginning.  */		curp = runp;		obstack_1grow_fast (&extrapool, curp->nmbs - 1);		for (i = 1; i < curp->nmbs; ++i)		  obstack_1grow_fast (&extrapool, curp->mbs[i]);		/* Now find the end of the consecutive sequence and                   add all the indeces in the indirect pool.  */		do		  {		    weightidx = output_weight (&weightpool, collate, curp);		    if (sizeof (int32_t) == sizeof (int))		      obstack_int_grow (&indirectpool, weightidx);		    else		      obstack_grow (&indirectpool, &weightidx,				    sizeof (int32_t));		    curp = curp->mblast;		  }		while (curp != series_startp);		/* Add the final weight.  */		weightidx = output_weight (&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.  */		for (i = 1; i < curp->nmbs; ++i)		  obstack_1grow_fast (&extrapool, curp->mbs[i]);	      }	    else	      {		/* A single entry.  Simply add the index and the length and		   string (except for the first character which is already		   tested for).  */		int i;		/* Output the weight info.  */		weightidx = output_weight (&weightpool, collate, runp);		added = ((sizeof (int32_t) + 1 + runp->nmbs - 1			  + __alignof__ (int32_t) - 1)			 & ~(__alignof__ (int32_t) - 1));		obstack_make_room (&extrapool, added);		if (sizeof (int32_t) == sizeof (int))		  obstack_int_grow_fast (&extrapool, weightidx);		else		  obstack_grow (&extrapool, &weightidx, sizeof (int32_t));		obstack_1grow_fast (&extrapool, runp->nmbs - 1);		for (i = 1; i < runp->nmbs; ++i)		  obstack_1grow_fast (&extrapool, runp->mbs[i]);	      }	    /* Add alignment bytes if necessary.  */	    while ((obstack_object_size (&extrapool)		    & (__alignof__ (int32_t) - 1)) != 0)	      obstack_1grow_fast (&extrapool, '\0');	    /* Next entry.  */	    lastp = runp;	    runp = runp->mbnext;	  }	while (runp != NULL);	/* If the final entry in the list is not a single character we           add an UNDEFINED entry here.  */	if (lastp->nmbs != 1)	  {	    int added = ((sizeof (int32_t) + 1 + 1 + __alignof__ (int32_t))			 & ~(__alignof__ (int32_t) - 1));	    obstack_make_room (&extrapool, added);	    if (sizeof (int32_t) == sizeof (int))	      obstack_int_grow_fast (&extrapool, 0);	    else	      {		int32_t zero = 0;		obstack_grow (&extrapool, &zero, sizeof (int32_t));	      }	    /* XXX What rule? We just pick the first.  */	    obstack_1grow_fast (&extrapool, 0);	    /* Length is zero.  */	    obstack_1grow_fast (&extrapool, 0);	    /* Add alignment bytes if necessary.  */	    while ((obstack_object_size (&extrapool)		    & (__alignof__ (int32_t) - 1)) != 0)	      obstack_1grow_fast (&extrapool, '\0');	  }      }  /* Add padding to the tables if necessary.  */  while ((obstack_object_size (&weightpool) & (__alignof__ (int32_t) - 1))	 != 0)    obstack_1grow (&weightpool, 0);  /* Now add the four tables.  */  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_TABLEMB));  iov[2 + cnt].iov_base = tablemb;  iov[2 + cnt].iov_len = sizeof (tablemb);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  assert ((iov[2 + cnt].iov_len & (__alignof__ (int32_t) - 1)) == 0);  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_WEIGHTMB));  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);  iov[2 + cnt].iov_base = obstack_finish (&weightpool);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_EXTRAMB));  iov[2 + cnt].iov_len = obstack_object_size (&extrapool);  iov[2 + cnt].iov_base = obstack_finish (&extrapool);  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;  assert ((iov[2 + cnt].iov_len & (__alignof__ (int32_t) - 1)) == 0);  ++cnt;  /* Now the same for the wide character table.  We need to store some     more information here.  */  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_HASH_SIZE));  iov[2 + cnt].iov_base = &collate->plane_size;  iov[2 + cnt].iov_len = sizeof (collate->plane_size);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_HASH_LAYERS));  iov[2 + cnt].iov_base = &collate->plane_cnt;  iov[2 + cnt].iov_len = sizeof (collate->plane_cnt);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  ++cnt;  /* Construct a table with the names.  The size of the table is the same     as the table with the pointers.  */  table_size = collate->plane_size * collate->plane_cnt;  names = (uint32_t *) alloca (table_size * sizeof (uint32_t));  for (ch = 0; ch < table_size; ++ch)    if (collate->wcheads[ch] == NULL)      names[ch] = 0;    else      names[ch] = collate->wcheads[ch]->wcs[0];  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_NAMES));  iov[2 + cnt].iov_base = names;  iov[2 + cnt].iov_len = table_size * sizeof (uint32_t);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  ++cnt;  /* Since we are using the sign of an integer to mark indirection the     offsets in the arrays we are indirectly referring to must not be     zero since -0 == 0.  Therefore we add a bit of dummy content.  */  if (sizeof (int) == sizeof (int32_t))    {      obstack_int_grow (&extrapool, 0);      obstack_int_grow (&indirectpool, 0);    }  else    {      int32_t zero = 0;      obstack_grow (&extrapool, &zero, sizeof (zero));      obstack_grow (&indirectpool, &zero, sizeof (zero));    }  /* Now insert the `UNDEFINED' value if it is used.  Since this value     will probably be used more than once it is good to store the     weights only once.  */  if (output_weightwc (&weightpool, collate, &collate->undefined) != 0)    abort ();  /* Generate the table.  Walk through the lists of sequences starting     with the same wide character and add them one after the other to     the table.  In case we have more than one sequence starting with     the same byte we have to use extra indirection.  */  tablewc = (uint32_t *) alloca (table_size * sizeof (uint32_t));  for (ch = 0; ch < table_size; ++ch)    if (collate->wcheads[ch] == NULL)      {	/* Set the entry to zero.  */	tablewc[ch] = 0;      }    else if (collate->wcheads[ch]->wcnext == NULL	     && collate->wcheads[ch]->nwcs == 1)      {	tablewc[ch] = output_weightwc (&weightpool, collate,				       collate->wcheads[ch]);      }    else      {	/* As for the singlebyte table, we recognize sequences and	   compress them.  */	struct element_t *runp = collate->wcheads[ch];	struct element_t *lastp;	tablewc[ch] = -(obstack_object_size (&extrapool) / sizeof (uint32_t));	do	  {	    /* Store the current index in the weight table.  We know that	       the current position in the `extrapool' is aligned on a	       32-bit address.  */	    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]))	      {		int i;		/* Now add first the initial byte sequence.  */		added = (1 + 1 + 2 * (runp->nwcs - 1)) * sizeof (int32_t);		if (sizeof (int32_t) == sizeof (int))		  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,					   obstack_object_size (&indirectpool)					   / sizeof (int32_t));		    obstack_int_grow_fast (&extrapool, runp->nwcs - 1);		  }		else		  {		    int32_t i = (obstack_object_size (&indirectpool)				 / sizeof (int32_t));		    obstack_grow (&extrapool, &i, sizeof (int32_t));		    i = runp->nwcs - 1;		    obstack_grow (&extrapool, &i, sizeof (int32_t));		  }		for (i = 1; i < runp->nwcs; ++i)		  if (sizeof (int32_t) == sizeof (int))		    obstack_int_grow_fast (&extrapool, runp->wcs[i]);		  else		    obstack_grow (&extrapool, &runp->wcs[i], sizeof (int32_t));		/* 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 (&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);		  }		/* And add the end byte sequence.  Without length this                   time.  */		for (i = 1; i < runp->nwcs; ++i)		  if (sizeof (int32_t) == sizeof (int))		    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	      {		/* A single entry.  Simply add the index and the length and		   string (except for the first character which is already		   tested for).  */		int i;		added = (1 + 1 + runp->nwcs - 1) * sizeof (int32_t);		if (sizeof (int) == sizeof (int32_t))		  obstack_make_room (&extrapool, added);		if (sizeof (int32_t) == sizeof (int))		  {		    obstack_int_grow_fast (&extrapool, weightidx);		    obstack_int_grow_fast (&extrapool, runp->nwcs - 1);		  }		else		  {		    int32_t l = runp->nwcs - 1;		    obstack_grow (&extrapool, &weightidx, sizeof (int32_t));		    obstack_grow (&extrapool, &l, sizeof (int32_t));		  }		for (i = 1; i < runp->nwcs; ++i)		  if (sizeof (int32_t) == sizeof (int))		    obstack_int_grow_fast (&extrapool, runp->wcs[i]);		  else		    obstack_grow (&extrapool, &runp->wcs[i], sizeof (int32_t));	      }	    /* Next entry.  */	    lastp = runp;	    runp = runp->wcnext;	  }	while (runp != NULL);      }  /* Now add the four tables.  */  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_TABLEWC));  iov[2 + cnt].iov_base = tablewc;  iov[2 + cnt].iov_len = table_size * sizeof (uint32_t);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_WEIGHTWC));  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);  iov[2 + cnt].iov_base = obstack_finish (&weightpool);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_EXTRAWC));  iov[2 + cnt].iov_len = obstack_object_size (&extrapool);  iov[2 + cnt].iov_base = obstack_finish (&extrapool);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_INDIRECTWC));  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;  assert (iov[2 + cnt].iov_len % sizeof (int32_t) == 0);  ++cnt;  /* Finally write the table with collation element names out.  It is     a hash table with a simple function which gets the name of the     character as the input.  One character might have many names.  The     value associated with the name is an index into the weight table     where we are then interested in the first-level weight value.     To determine how large the table should be we are counting the     elements have to put in.  Since we are using internal chaining     using a secondary hash function we have to make the table a bit     larger to avoid extremely long search times.  We can achieve     good results with a 40% larger table than there are entries.  */  elem_size = 0;  runp = collate->start;  while (runp != NULL)    {      if (runp->mbs != NULL && runp->weights != NULL)	/* Yep, the element really counts.  */	++elem_size;      runp = runp->next;    }  /* Add 40% and find the next prime number.  */  elem_size = MIN (next_prime (elem_size * 1.4), 257);  /* Allocate the table.  Each entry consists of two words: the hash     value and an index in a secondary table which provides the index     into the weight table and the string itself (so that a match can     be determined).  */  elem_table = (uint32_t *) obstack_alloc (&extrapool,					   elem_size * 2 * sizeof (uint32_t));  memset (elem_table, '\0', elem_size * 2 * sizeof (uint32_t));  /* Now add the elements.  */  runp = collate->start;  while (runp != NULL)    {      if (runp->mbs != NULL && runp->weights != NULL)	{	  /* Compute the hash value of the name.  */	  uint32_t namelen = strlen (runp->name);	  uint32_t hash = elem_hash (runp->name, namelen);	  size_t idx = hash % elem_size;	  if (elem_table[idx * 2] != 0)	    {	      /* The spot is already take.  Try iterating using the value		 from the secondary hashing function.  */	      size_t iter = hash % (elem_size - 2);	      do		{		  idx += iter;		  if (idx >= elem_size)		    idx -= elem_size;		}	      while (elem_table[idx * 2] != 0);	      /* This is the spot where we will insert the value.  */	      elem_table[idx * 2] = hash;	      elem_table[idx * 2 + 1] = obstack_object_size (&extrapool);	      /* The the string itself including length.  */	      obstack_1grow (&extrapool, namelen);	      obstack_grow (&extrapool, runp->name, namelen);	      /* And the multibyte representation.  */	      obstack_1grow (&extrapool, runp->nmbs);	      obstack_grow (&extrapool, runp->mbs, runp->nmbs);	      /* And align again to 32 bits.  */	      if ((1 + namelen + 1 + runp->nmbs) % sizeof (int32_t) != 0)		obstack_grow (&extrapool, "\0\0",			      (sizeof (int32_t)			       - ((1 + namelen + 1 + runp->nmbs)				  % sizeof (int32_t))));	    }	}      runp = runp->next;    }  /* Prepare to write out this data.  */  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB));  iov[2 + cnt].iov_base = &elem_size;  iov[2 + cnt].iov_len = sizeof (int32_t);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_TABLEMB));  iov[2 + cnt].iov_base = elem_table;  iov[2 + cnt].iov_len = elem_size * 2 * sizeof (int32_t);  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_EXTRAMB));  iov[2 + cnt].iov_len = obstack_object_size (&extrapool);  iov[2 + cnt].iov_base = obstack_finish (&extrapool);  ++cnt;  assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));  write_locale_data (output_path, "LC_COLLATE", 2 + cnt, iov);  obstack_free (&weightpool, NULL);  obstack_free (&extrapool, NULL);  obstack_free (&indirectpool, NULL);}