for (;;) {
_nl_find_msg (domain_file, msgid, index)     struct loaded_l10nfile *domain_file;     const char *msgid;     unsigned long int index;{  struct loaded_domain *domain;  size_t act;  char *result;  if (domain_file->decided == 0)    _nl_load_domain (domain_file);  if (domain_file->data == NULL)    return NULL;  domain = (struct loaded_domain *) domain_file->data;  /* Locate the MSGID and its translation.  */  if (domain->hash_size > 2 && domain->hash_tab != NULL)    {      /* Use the hashing table.  */      nls_uint32 len = strlen (msgid);      nls_uint32 hash_val = hash_string (msgid);      nls_uint32 idx = hash_val % domain->hash_size;      nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));      nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);      if (nstr == 0)	/* Hash table entry is empty.  */	return NULL;      if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len	  && strcmp (msgid,		     domain->data + W (domain->must_swap,				       domain->orig_tab[nstr - 1].offset)) == 0)	{	  act = nstr - 1;	  goto found;	}      while (1)	{	  if (idx >= domain->hash_size - incr)	    idx -= domain->hash_size - incr;	  else	    idx += incr;	  nstr = W (domain->must_swap, domain->hash_tab[idx]);	  if (nstr == 0)	    /* Hash table entry is empty.  */	    return NULL;	  if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len	      && (strcmp (msgid,			  domain->data + W (domain->must_swap,					    domain->orig_tab[nstr - 1].offset))		  == 0))	    {	      act = nstr - 1;	      goto found;	    }	}      /* NOTREACHED */    }  else    {      /* Try the default method:  binary search in the sorted array of	 messages.  */      size_t top, bottom;      bottom = 0;      top = domain->nstrings;      while (bottom < top)	{	  int cmp_val;	  act = (bottom + top) / 2;	  cmp_val = strcmp (msgid, (domain->data				    + W (domain->must_swap,					 domain->orig_tab[act].offset)));	  if (cmp_val < 0)	    top = act;	  else if (cmp_val > 0)	    bottom = act + 1;	  else	    goto found;	}      /* No translation was found.  */      return NULL;    } found:  /* The translation was found at index ACT.  If we have to convert the     string to use a different character set, this is the time.  */  result = (char *) domain->data	   + W (domain->must_swap, domain->trans_tab[act].offset);#if defined _LIBC || HAVE_ICONV  if (# ifdef _LIBC      domain->conv != (__gconv_t) -1# else#  if HAVE_ICONV      domain->conv != (iconv_t) -1#  endif# endif      )    {      /* We are supposed to do a conversion.  First allocate an	 appropriate table with the same structure as the table	 of translations in the file, where we can put the pointers	 to the converted strings in.	 The is a slight complication with the INDEX: We don't know	 a priori which entries are plural entries. Therefore at any	 moment we can only translate the variants 0 .. INDEX.  */      if (domain->conv_tab == NULL	  && ((domain->conv_tab = (char **) calloc (domain->nstrings,						    sizeof (char *)))	      == NULL))	/* Mark that we didn't succeed allocating a table.  */	domain->conv_tab = (char **) -1;      if (domain->conv_tab == (char **) -1)	/* Nothing we can do, no more memory.  */	goto converted;      if (domain->conv_tab[act] == NULL	  || *(nls_uint32 *) domain->conv_tab[act] < index)	{	  /* We haven't used this string so far, so it is not	     translated yet.  Do this now.  */	  /* We use a bit more efficient memory handling.	     We allocate always larger blocks which get used over	     time.  This is faster than many small allocations.   */	  __libc_lock_define_initialized (static, lock)	  static unsigned char *freemem;	  static size_t freemem_size;	  size_t resultlen;	  const unsigned char *inbuf;	  unsigned char *outbuf;	  /* Note that we translate (index + 1) consecutive strings at	     once, including the final NUL byte.  */	  {	    unsigned long int i = index;	    char *p = result;	    do	      p += strlen (p) + 1;	    while (i-- > 0);	    resultlen = p - result;	  }	  inbuf = result;	  outbuf = freemem + 4;	  __libc_lock_lock (lock);# ifdef _LIBC	  {	    size_t written;	    int res;	    while ((res = __gconv (domain->conv,				   &inbuf, inbuf + resultlen,				   &outbuf, outbuf + freemem_size,				   &written)) == __GCONV_OK)	      {		if (res != __GCONV_FULL_OUTPUT)		  goto out;		/* We must resize the buffer.  */		freemem_size = MAX (2 * freemem_size, 4064);		freemem = (char *) malloc (freemem_size);		if (freemem == NULL)		  goto out;		inbuf = result;		outbuf = freemem + 4;	      }	  }# else#  if HAVE_ICONV	  for (;;)	    {	      const char *inptr = (const char *) inbuf;	      size_t inleft = resultlen;	      char *outptr = (char *) outbuf;	      size_t outleft = freemem_size;	      if (iconv (domain->conv, &inptr, &inleft, &outptr, &outleft)		  != (size_t)(-1))		{		  outbuf = (unsigned char *) outptr;		  break;		}	      if (errno != E2BIG)		goto out;	      /* We must resize the buffer.  */	      freemem_size = 2 * freemem_size;	      if (freemem_size < 4064)		freemem_size = 4064;	      freemem = (char *) malloc (freemem_size);	      if (freemem == NULL)		goto out;	      outbuf = freemem + 4;	    }#  endif# endif	  /* We have now in our buffer a converted string.  Put this	     into the table of conversions.  */	  *(nls_uint32 *) freemem = index;	  domain->conv_tab[act] = freemem;	  /* Shrink freemem, but keep it aligned.  */	  freemem_size -= outbuf - freemem;	  freemem = outbuf;	  freemem += freemem_size & 3;	  freemem_size = freemem_size & ~3;	out:	  __libc_lock_unlock (lock);	}      /* Now domain->conv_tab[act] contains the translation of at least	 the variants 0 .. INDEX.  */      result = domain->conv_tab[act] + 4;    } converted:  /* The result string is converted.  */#endif /* _LIBC || HAVE_ICONV */  /* Now skip some strings.  How much depends on the index passed in.  */  while (index-- > 0)    {#ifdef _LIBC      result = __rawmemchr (result, '\0');#else      result = strchr (result, '\0');#endif      /* And skip over the NUL byte.  */      ++result;    }  return result;}