sorted = alloca (number * sizeof (struct translit_t **));
sorted = (struct translit_t **) alloca (number * sizeof (struct translit_t **));
allocate_arrays (struct locale_ctype_t *ctype, struct charmap_t *charmap,		 struct repertoire_t *repertoire){  size_t idx;  /* First we have to decide how we organize the arrays.  It is easy     for a one-byte character set.  But multi-byte character set     cannot be stored flat because the chars might be sparsely used.     So we determine an optimal hashing function for the used     characters.     We use a very trivial hashing function to store the sparse     table.  CH % TABSIZE is used as an index.  To solve multiple hits     we have N planes.  This guarantees a fixed search time for a     character [N / 2].  In the following code we determine the minimum     value for TABSIZE * N, where TABSIZE >= 256.  */  size_t min_total = UINT_MAX;  size_t act_size = 256;  if (!be_quiet)    fputs (_("\Computing table size for character classes might take a while..."),	   stderr);  while (act_size < min_total)    {      size_t cnt[act_size];      size_t act_planes = 1;      memset (cnt, '\0', sizeof cnt);      for (idx = 0; idx < 256; ++idx)	cnt[idx] = 1;      for (idx = 0; idx < ctype->charnames_act; ++idx)	if (ctype->charnames[idx] >= 256)	  {	    size_t nr = ctype->charnames[idx] % act_size;	    if (++cnt[nr] > act_planes)	      {		act_planes = cnt[nr];		if (act_size * act_planes >= min_total)		  break;	      }	  }      if (act_size * act_planes < min_total)	{	  min_total = act_size * act_planes;	  ctype->plane_size = act_size;	  ctype->plane_cnt = act_planes;	}      ++act_size;    }  if (!be_quiet)    fputs (_(" done\n"), stderr);  ctype->names = (uint32_t *) xcalloc (ctype->plane_size				       * ctype->plane_cnt,				       sizeof (uint32_t));  for (idx = 1; idx < 256; ++idx)    ctype->names[idx] = idx;  /* Trick: change the 0th entry's name to 1 to mark the cell occupied.  */  ctype->names[0] = 1;  for (idx = 256; idx < ctype->charnames_act; ++idx)    {      size_t nr = (ctype->charnames[idx] % ctype->plane_size);      size_t depth = 0;      while (ctype->names[nr + depth * ctype->plane_size])	++depth;      assert (depth < ctype->plane_cnt);      ctype->names[nr + depth * ctype->plane_size] = ctype->charnames[idx];      /* Now for faster access remember the index in the NAMES_B array.  */      ctype->charnames[idx] = nr + depth * ctype->plane_size;    }  ctype->names[0] = 0;  /* You wonder about this amount of memory?  This is only because some     users do not manage to address the array with unsigned values or     data types with range >= 256.  '\200' would result in the array     index -128.  To help these poor people we duplicate the entries for     128 up to 255 below the entry for \0.  */  ctype->ctype_b = (char_class_t *) xcalloc (256 + 128,					     sizeof (char_class_t));  ctype->ctype32_b = (char_class32_t *) xcalloc (ctype->plane_size						 * ctype->plane_cnt,						 sizeof (char_class32_t));  /* This is the array accessed using the multibyte string elements.  */  for (idx = 0; idx < 256; ++idx)    ctype->ctype_b[128 + idx] = ctype->class256_collection[idx];  /* Mirror first 127 entries.  We must take care that entry -1 is not     mirrored because EOF == -1.  */  for (idx = 0; idx < 127; ++idx)    ctype->ctype_b[idx] = ctype->ctype_b[256 + idx];  /* The 32 bit array contains all characters.  */  for (idx = 0; idx < ctype->class_collection_act; ++idx)    ctype->ctype32_b[ctype->charnames[idx]] = ctype->class_collection[idx];  /* Room for table of mappings.  */  ctype->map = (uint32_t **) xmalloc (ctype->map_collection_nr				      * sizeof (uint32_t *));  /* Fill in all mappings.  */  for (idx = 0; idx < ctype->map_collection_nr; ++idx)    {      unsigned int idx2;      /* Allocate table.  */      ctype->map[idx] = (uint32_t *) xmalloc ((ctype->plane_size					       * ctype->plane_cnt + 128)					      * sizeof (uint32_t));      /* Copy default value (identity mapping).  */      memcpy (&ctype->map[idx][128], ctype->names,	      ctype->plane_size * ctype->plane_cnt * sizeof (uint32_t));      /* Copy values from collection.  */      for (idx2 = 0; idx2 < 256; ++idx2)	ctype->map[idx][128 + idx2] = ctype->map256_collection[idx][idx2];      /* Mirror first 127 entries.  We must take care not to map entry	 -1 because EOF == -1.  */      for (idx2 = 0; idx2 < 127; ++idx2)	ctype->map[idx][idx2] = ctype->map[idx][256 + idx2];      /* EOF must map to EOF.  */      ctype->map[idx][127] = EOF;    }  /* Extra array for class and map names.  */  ctype->class_name_ptr = (uint32_t *) xmalloc (ctype->nr_charclass						* sizeof (uint32_t));  ctype->map_name_ptr = (uint32_t *) xmalloc (ctype->map_collection_nr					      * sizeof (uint32_t));  /* Array for width information.  Because the expected width are very     small we use only one single byte.  This save space and we need     not provide the information twice with both endianesses.  */  ctype->width = (unsigned char *) xmalloc (ctype->plane_size					    * ctype->plane_cnt);  /* Initialize with default width value.  */  memset (ctype->width, charmap->width_default,	  ctype->plane_size * ctype->plane_cnt);  if (charmap->width_rules != NULL)    {#if 0      size_t cnt;      for (cnt = 0; cnt < charmap->nwidth_rules; ++cnt)	if (charmap->width_rules[cnt].width != charmap->width_default)	  for (idx = charmap->width_rules[cnt].from;	       idx <= charmap->width_rules[cnt].to; ++idx)	    {	      size_t nr = idx % ctype->plane_size;	      size_t depth = 0;	      while (ctype->names[nr + depth * ctype->plane_size] != nr)		++depth;	      assert (depth < ctype->plane_cnt);	      ctype->width[nr + depth * ctype->plane_size]		= charmap->width_rules[cnt].width;	    }#else      abort ();#endif    }  /* Set MB_CUR_MAX.  */  ctype->mb_cur_max = charmap->mb_cur_max;  /* We need the name of the currently used 8-bit character set to     make correct conversion between this 8-bit representation and the     ISO 10646 character set used internally for wide characters.  */  ctype->codeset_name = charmap->code_set_name;  /* Now determine the table for the transliteration information.     XXX It is not yet clear to me whether it is worth implementing a     complicated algorithm which uses a hash table to locate the entries.     For now I'll use a simple array which can be searching using binary     search.  */  if (ctype->translit_copy_locale != NULL)    {      /* Fold in the transliteration information from the locale mentioned	 in the `include' statement.  */      struct locale_ctype_t *here = ctype;      do	{	  struct localedef_t *other = find_locale (LC_CTYPE,						   here->translit_copy_locale,						   repertoire->name, charmap);	  if (other == NULL)	    {	      error (0, 0, _("\%s: transliteration data from locale `%s' not available"),		     "LC_CTYPE", here->translit_copy_locale);	      break;	    }	  here = other->categories[LC_CTYPE].ctype;	  /* Enqueue the information if necessary.  */	  if (here->translit != NULL)	    {	      struct translit_t *endp = here->translit;	      while (endp->next != NULL)		endp = endp->next;	      endp->next = ctype->translit;	      ctype->translit = here->translit;	    }	}      while (here->translit_copy_locale != NULL);    }  if (ctype->translit != NULL)    {      /* First count how many entries we have.  This is the upper limit	 since some entries from the included files might be overwritten.  */      size_t number = 0;      size_t cnt;      struct translit_t *runp = ctype->translit;      struct translit_t **sorted;      size_t from_len, to_len;      while (runp != NULL)	{	  ++number;	  runp = runp->next;	}      /* Next we allocate an array large enough and fill in the values.  */      sorted = alloca (number * sizeof (struct translit_t **));      runp = ctype->translit;      number = 0;      do	{	  /* Search for the place where to insert this string.	     XXX Better use a real sorting algorithm later.  */	  size_t idx = 0;	  int replace = 0;	  while (idx < number)	    {	      int res = wcscmp ((const wchar_t *) sorted[idx]->from,				(const wchar_t *) runp->from);	      if (res == 0)		{		  replace = 1;		  break;		}	      if (res > 0)		break;	      ++idx;	    }	  if (replace)	    sorted[idx] = runp;	  else	    {	      memmove (&sorted[idx + 1], &sorted[idx],		       (number - idx) * sizeof (struct translit_t *));	      sorted[idx] = runp;	      ++number;	    }	  runp = runp->next;	}      while (runp != NULL);      /* The next step is putting all the possible transliteration	 strings in one memory block so that we can write it out.	 We need several different blocks:	 - index to the tfromstring array	 - from-string array	 - index to the to-string array	 - to-string array.	 And this all must be available for both endianes variants.      */      from_len = to_len = 0;      for (cnt = 0; cnt < number; ++cnt)	{	  struct translit_to_t *srunp;	  from_len += wcslen ((const wchar_t *) sorted[cnt]->from) + 1;	  srunp = sorted[cnt]->to;	  while (srunp != NULL)	    {	      to_len += wcslen ((const wchar_t *) srunp->str) + 1;	      srunp = srunp->next;	    }	  /* Plus one for the extra NUL character marking the end of	     the list for the current entry.  */	  ++to_len;	}      /* We can allocate the arrays for the results.  */      ctype->translit_from_idx = xmalloc (number * sizeof (uint32_t));      ctype->translit_from_tbl = xmalloc (from_len * sizeof (uint32_t));      ctype->translit_to_idx = xmalloc (number * sizeof (uint32_t));      ctype->translit_to_tbl = xmalloc (to_len * sizeof (uint32_t));      from_len = 0;      to_len = 0;      for (cnt = 0; cnt < number; ++cnt)	{	  size_t len;	  struct translit_to_t *srunp;	  ctype->translit_from_idx[cnt] = from_len;	  ctype->translit_to_idx[cnt] = to_len;	  len = wcslen ((const wchar_t *) sorted[cnt]->from) + 1;	  wmemcpy ((wchar_t *) &ctype->translit_from_tbl[from_len],		   (const wchar_t *) sorted[cnt]->from, len);	  from_len += len;	  ctype->translit_to_idx[cnt] = to_len;	  srunp = sorted[cnt]->to;	  while (srunp != NULL)	    {	      len = wcslen ((const wchar_t *) srunp->str) + 1;	      wmemcpy ((wchar_t *) &ctype->translit_to_tbl[to_len],		       (const wchar_t *) srunp->str, len);	      to_len += len;	      srunp = srunp->next;	    }	  ctype->translit_to_tbl[to_len++] = L'\0';	}      /* Store the information about the length.  */      ctype->translit_idx_size = number * sizeof (uint32_t);      ctype->translit_from_tbl_size = from_len * sizeof (uint32_t);      ctype->translit_to_tbl_size = to_len * sizeof (uint32_t);    }  else    {      /* Provide some dummy pointers since we have nothing to write out.  */      static uint32_t no_str = { 0 };      ctype->translit_from_idx = &no_str;      ctype->translit_from_tbl = &no_str;      ctype->translit_to_tbl = &no_str;      ctype->translit_idx_size = 0;      ctype->translit_from_tbl_size = 0;      ctype->translit_to_tbl_size = 0;    }}