Blame intl/finddomain.c

Packit Service 82fcde
/* Handle list of needed message catalogs
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   Written by Ulrich Drepper <drepper@gnu.org>, 1995.
Packit Service 82fcde
Packit Service 82fcde
   This program is free software: you can redistribute it and/or modify
Packit Service 82fcde
   it under the terms of the GNU Lesser General Public License as published by
Packit Service 82fcde
   the Free Software Foundation; either version 2.1 of the License, or
Packit Service 82fcde
   (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   This program is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 82fcde
   GNU Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public License
Packit Service 82fcde
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#ifdef HAVE_CONFIG_H
Packit Service 82fcde
# include <config.h>
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
Packit Service 82fcde
#if defined HAVE_UNISTD_H || defined _LIBC
Packit Service 82fcde
# include <unistd.h>
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#include "gettextP.h"
Packit Service 82fcde
#ifdef _LIBC
Packit Service 82fcde
# include <libintl.h>
Packit Service 82fcde
#else
Packit Service 82fcde
# include "libgnuintl.h"
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Handle multi-threaded applications.  */
Packit Service 82fcde
#ifdef _LIBC
Packit Service 82fcde
# include <libc-lock.h>
Packit Service 82fcde
# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
Packit Service 82fcde
# define gl_rwlock_rdlock __libc_rwlock_rdlock
Packit Service 82fcde
# define gl_rwlock_wrlock __libc_rwlock_wrlock
Packit Service 82fcde
# define gl_rwlock_unlock __libc_rwlock_unlock
Packit Service 82fcde
#else
Packit Service 82fcde
# include "lock.h"
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* @@ end of prolog @@ */
Packit Service 82fcde
/* List of already loaded domains.  */
Packit Service 82fcde
static struct loaded_l10nfile *_nl_loaded_domains;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Return a data structure describing the message catalog described by
Packit Service 82fcde
   the DOMAINNAME and CATEGORY parameters with respect to the currently
Packit Service 82fcde
   established bindings.  */
Packit Service 82fcde
struct loaded_l10nfile *
Packit Service 82fcde
_nl_find_domain (const char *dirname, char *locale,
Packit Service 82fcde
		 const char *domainname, struct binding *domainbinding)
Packit Service 82fcde
{
Packit Service 82fcde
  struct loaded_l10nfile *retval;
Packit Service 82fcde
  const char *language;
Packit Service 82fcde
  const char *modifier;
Packit Service 82fcde
  const char *territory;
Packit Service 82fcde
  const char *codeset;
Packit Service 82fcde
  const char *normalized_codeset;
Packit Service 82fcde
  const char *alias_value;
Packit Service 82fcde
  int mask;
Packit Service 82fcde
Packit Service 82fcde
  /* LOCALE can consist of up to four recognized parts for the XPG syntax:
Packit Service 82fcde
Packit Service 82fcde
		language[_territory][.codeset][@modifier]
Packit Service 82fcde
Packit Service 82fcde
     Beside the first part all of them are allowed to be missing.  If
Packit Service 82fcde
     the full specified locale is not found, the less specific one are
Packit Service 82fcde
     looked for.  The various parts will be stripped off according to
Packit Service 82fcde
     the following order:
Packit Service 82fcde
		(1) codeset
Packit Service 82fcde
		(2) normalized codeset
Packit Service 82fcde
		(3) territory
Packit Service 82fcde
		(4) modifier
Packit Service 82fcde
   */
Packit Service 82fcde
Packit Service 82fcde
  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
Packit Service 82fcde
  gl_rwlock_define_initialized (static, lock);
Packit Service 82fcde
  gl_rwlock_rdlock (lock);
Packit Service 82fcde
Packit Service 82fcde
  /* If we have already tested for this locale entry there has to
Packit Service 82fcde
     be one data set in the list of loaded domains.  */
Packit Service 82fcde
  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
Packit Service 82fcde
			       strlen (dirname) + 1, 0, locale, NULL, NULL,
Packit Service 82fcde
			       NULL, NULL, domainname, 0);
Packit Service 82fcde
Packit Service 82fcde
  gl_rwlock_unlock (lock);
Packit Service 82fcde
Packit Service 82fcde
  if (retval != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We know something about this locale.  */
Packit Service 82fcde
      int cnt;
Packit Service 82fcde
Packit Service 82fcde
      if (retval->decided <= 0)
Packit Service 82fcde
	_nl_load_domain (retval, domainbinding);
Packit Service 82fcde
Packit Service 82fcde
      if (retval->data != NULL)
Packit Service 82fcde
	return retval;
Packit Service 82fcde
Packit Service 82fcde
      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (retval->successor[cnt]->decided <= 0)
Packit Service 82fcde
	    _nl_load_domain (retval->successor[cnt], domainbinding);
Packit Service 82fcde
Packit Service 82fcde
	  if (retval->successor[cnt]->data != NULL)
Packit Service 82fcde
	    break;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      return retval;
Packit Service 82fcde
      /* NOTREACHED */
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* See whether the locale value is an alias.  If yes its value
Packit Service 82fcde
     *overwrites* the alias name.  No test for the original value is
Packit Service 82fcde
     done.  */
Packit Service 82fcde
  alias_value = _nl_expand_alias (locale);
Packit Service 82fcde
  if (alias_value != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t len = strlen (alias_value) + 1;
Packit Service 82fcde
      locale = (char *) malloc (len);
Packit Service 82fcde
      if (locale == NULL)
Packit Service 82fcde
	return NULL;
Packit Service 82fcde
Packit Service 82fcde
      memcpy (locale, alias_value, len);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Now we determine the single parts of the locale name.  First
Packit Service 82fcde
     look for the language.  Termination symbols are `_', '.', and `@'.  */
Packit Service 82fcde
  mask = _nl_explode_name (locale, &language, &modifier, &territory,
Packit Service 82fcde
			   &codeset, &normalized_codeset);
Packit Service 82fcde
  if (mask == -1)
Packit Service 82fcde
    /* This means we are out of core.  */
Packit Service 82fcde
    return NULL;
Packit Service 82fcde
Packit Service 82fcde
  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
Packit Service 82fcde
  gl_rwlock_wrlock (lock);
Packit Service 82fcde
Packit Service 82fcde
  /* Create all possible locale entries which might be interested in
Packit Service 82fcde
     generalization.  */
Packit Service 82fcde
  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
Packit Service 82fcde
			       strlen (dirname) + 1, mask, language, territory,
Packit Service 82fcde
			       codeset, normalized_codeset, modifier,
Packit Service 82fcde
			       domainname, 1);
Packit Service 82fcde
Packit Service 82fcde
  gl_rwlock_unlock (lock);
Packit Service 82fcde
Packit Service 82fcde
  if (retval == NULL)
Packit Service 82fcde
    /* This means we are out of core.  */
Packit Service 82fcde
    goto out;
Packit Service 82fcde
Packit Service 82fcde
  if (retval->decided <= 0)
Packit Service 82fcde
    _nl_load_domain (retval, domainbinding);
Packit Service 82fcde
  if (retval->data == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      int cnt;
Packit Service 82fcde
      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (retval->successor[cnt]->decided <= 0)
Packit Service 82fcde
	    _nl_load_domain (retval->successor[cnt], domainbinding);
Packit Service 82fcde
	  if (retval->successor[cnt]->data != NULL)
Packit Service 82fcde
	    break;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The room for an alias was dynamically allocated.  Free it now.  */
Packit Service 82fcde
  if (alias_value != NULL)
Packit Service 82fcde
    free (locale);
Packit Service 82fcde
Packit Service 82fcde
out:
Packit Service 82fcde
  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
Packit Service 82fcde
  if (mask & XPG_NORM_CODESET)
Packit Service 82fcde
    free ((void *) normalized_codeset);
Packit Service 82fcde
Packit Service 82fcde
  return retval;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#ifdef _LIBC
Packit Service 82fcde
/* This is called from iconv/gconv_db.c's free_mem, as locales must
Packit Service 82fcde
   be freed before freeing gconv steps arrays.  */
Packit Service 82fcde
void __libc_freeres_fn_section
Packit Service 82fcde
_nl_finddomain_subfreeres (void)
Packit Service 82fcde
{
Packit Service 82fcde
  struct loaded_l10nfile *runp = _nl_loaded_domains;
Packit Service 82fcde
Packit Service 82fcde
  while (runp != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      struct loaded_l10nfile *here = runp;
Packit Service 82fcde
      if (runp->data != NULL)
Packit Service 82fcde
	_nl_unload_domain ((struct loaded_domain *) runp->data);
Packit Service 82fcde
      runp = runp->next;
Packit Service 82fcde
      free ((char *) here->filename);
Packit Service 82fcde
      free (here);
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
#endif