Blame intl/finddomain.c

Packit bbfece
/* Handle list of needed message catalogs
Packit bbfece
   Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
Packit bbfece
   Written by Ulrich Drepper <drepper@gnu.org>, 1995.
Packit bbfece
Packit bbfece
   This program is free software; you can redistribute it and/or modify it
Packit bbfece
   under the terms of the GNU Library General Public License as published
Packit bbfece
   by the Free Software Foundation; either version 2, or (at your option)
Packit bbfece
   any later version.
Packit bbfece
Packit bbfece
   This program is distributed in the hope that it will be useful,
Packit bbfece
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bbfece
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit bbfece
   Library General Public License for more details.
Packit bbfece
Packit bbfece
   You should have received a copy of the GNU Library General Public
Packit bbfece
   License along with this program; if not, write to the Free Software
Packit bbfece
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
Packit bbfece
   USA.  */
Packit bbfece
Packit bbfece
#ifdef HAVE_CONFIG_H
Packit bbfece
# include <config.h>
Packit bbfece
#endif
Packit bbfece
Packit bbfece
#include <stdio.h>
Packit bbfece
#include <sys/types.h>
Packit bbfece
#include <stdlib.h>
Packit bbfece
#include <string.h>
Packit bbfece
Packit bbfece
#if defined HAVE_UNISTD_H || defined _LIBC
Packit bbfece
# include <unistd.h>
Packit bbfece
#endif
Packit bbfece
Packit bbfece
#include "gettextP.h"
Packit bbfece
#ifdef _LIBC
Packit bbfece
# include <libintl.h>
Packit bbfece
#else
Packit bbfece
# include "libgnuintl.h"
Packit bbfece
#endif
Packit bbfece
Packit bbfece
/* @@ end of prolog @@ */
Packit bbfece
/* List of already loaded domains.  */
Packit bbfece
static struct loaded_l10nfile *_nl_loaded_domains;
Packit bbfece
Packit bbfece
Packit bbfece
/* Return a data structure describing the message catalog described by
Packit bbfece
   the DOMAINNAME and CATEGORY parameters with respect to the currently
Packit bbfece
   established bindings.  */
Packit bbfece
struct loaded_l10nfile *
Packit bbfece
internal_function
Packit bbfece
_nl_find_domain (dirname, locale, domainname, domainbinding)
Packit bbfece
     const char *dirname;
Packit bbfece
     char *locale;
Packit bbfece
     const char *domainname;
Packit bbfece
     struct binding *domainbinding;
Packit bbfece
{
Packit bbfece
  struct loaded_l10nfile *retval;
Packit bbfece
  const char *language;
Packit bbfece
  const char *modifier;
Packit bbfece
  const char *territory;
Packit bbfece
  const char *codeset;
Packit bbfece
  const char *normalized_codeset;
Packit bbfece
  const char *special;
Packit bbfece
  const char *sponsor;
Packit bbfece
  const char *revision;
Packit bbfece
  const char *alias_value;
Packit bbfece
  int mask;
Packit bbfece
Packit bbfece
  /* LOCALE can consist of up to four recognized parts for the XPG syntax:
Packit bbfece
Packit bbfece
		language[_territory[.codeset]][@modifier]
Packit bbfece
Packit bbfece
     and six parts for the CEN syntax:
Packit bbfece
Packit bbfece
	language[_territory][+audience][+special][,[sponsor][_revision]]
Packit bbfece
Packit bbfece
     Beside the first part all of them are allowed to be missing.  If
Packit bbfece
     the full specified locale is not found, the less specific one are
Packit bbfece
     looked for.  The various parts will be stripped off according to
Packit bbfece
     the following order:
Packit bbfece
		(1) revision
Packit bbfece
		(2) sponsor
Packit bbfece
		(3) special
Packit bbfece
		(4) codeset
Packit bbfece
		(5) normalized codeset
Packit bbfece
		(6) territory
Packit bbfece
		(7) audience/modifier
Packit bbfece
   */
Packit bbfece
Packit bbfece
  /* If we have already tested for this locale entry there has to
Packit bbfece
     be one data set in the list of loaded domains.  */
Packit bbfece
  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
Packit bbfece
			       strlen (dirname) + 1, 0, locale, NULL, NULL,
Packit bbfece
			       NULL, NULL, NULL, NULL, NULL, domainname, 0);
Packit bbfece
  if (retval != NULL)
Packit bbfece
    {
Packit bbfece
      /* We know something about this locale.  */
Packit bbfece
      int cnt;
Packit bbfece
Packit bbfece
      if (retval->decided == 0)
Packit bbfece
	_nl_load_domain (retval, domainbinding);
Packit bbfece
Packit bbfece
      if (retval->data != NULL)
Packit bbfece
	return retval;
Packit bbfece
Packit bbfece
      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
Packit bbfece
	{
Packit bbfece
	  if (retval->successor[cnt]->decided == 0)
Packit bbfece
	    _nl_load_domain (retval->successor[cnt], domainbinding);
Packit bbfece
Packit bbfece
	  if (retval->successor[cnt]->data != NULL)
Packit bbfece
	    break;
Packit bbfece
	}
Packit bbfece
      return cnt >= 0 ? retval : NULL;
Packit bbfece
      /* NOTREACHED */
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* See whether the locale value is an alias.  If yes its value
Packit bbfece
     *overwrites* the alias name.  No test for the original value is
Packit bbfece
     done.  */
Packit bbfece
  alias_value = _nl_expand_alias (locale);
Packit bbfece
  if (alias_value != NULL)
Packit bbfece
    {
Packit bbfece
#if defined _LIBC || defined HAVE_STRDUP
Packit bbfece
      locale = strdup (alias_value);
Packit bbfece
      if (locale == NULL)
Packit bbfece
	return NULL;
Packit bbfece
#else
Packit bbfece
      size_t len = strlen (alias_value) + 1;
Packit bbfece
      locale = (char *) malloc (len);
Packit bbfece
      if (locale == NULL)
Packit bbfece
	return NULL;
Packit bbfece
Packit bbfece
      memcpy (locale, alias_value, len);
Packit bbfece
#endif
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Now we determine the single parts of the locale name.  First
Packit bbfece
     look for the language.  Termination symbols are `_' and `@' if
Packit bbfece
     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
Packit bbfece
  mask = _nl_explode_name (locale, &language, &modifier, &territory,
Packit bbfece
			   &codeset, &normalized_codeset, &special,
Packit bbfece
			   &sponsor, &revision);
Packit bbfece
Packit bbfece
  /* Create all possible locale entries which might be interested in
Packit bbfece
     generalization.  */
Packit bbfece
  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
Packit bbfece
			       strlen (dirname) + 1, mask, language, territory,
Packit bbfece
			       codeset, normalized_codeset, modifier, special,
Packit bbfece
			       sponsor, revision, domainname, 1);
Packit bbfece
  if (retval == NULL)
Packit bbfece
    /* This means we are out of core.  */
Packit bbfece
    return NULL;
Packit bbfece
Packit bbfece
  if (retval->decided == 0)
Packit bbfece
    _nl_load_domain (retval, domainbinding);
Packit bbfece
  if (retval->data == NULL)
Packit bbfece
    {
Packit bbfece
      int cnt;
Packit bbfece
      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
Packit bbfece
	{
Packit bbfece
	  if (retval->successor[cnt]->decided == 0)
Packit bbfece
	    _nl_load_domain (retval->successor[cnt], domainbinding);
Packit bbfece
	  if (retval->successor[cnt]->data != NULL)
Packit bbfece
	    break;
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* The room for an alias was dynamically allocated.  Free it now.  */
Packit bbfece
  if (alias_value != NULL)
Packit bbfece
    free (locale);
Packit bbfece
Packit bbfece
  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
Packit bbfece
  if (mask & XPG_NORM_CODESET)
Packit bbfece
    free ((void *) normalized_codeset);
Packit bbfece
Packit bbfece
  return retval;
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
#ifdef _LIBC
Packit bbfece
libc_freeres_fn (free_mem)
Packit bbfece
{
Packit bbfece
  struct loaded_l10nfile *runp = _nl_loaded_domains;
Packit bbfece
Packit bbfece
  while (runp != NULL)
Packit bbfece
    {
Packit bbfece
      struct loaded_l10nfile *here = runp;
Packit bbfece
      if (runp->data != NULL)
Packit bbfece
	_nl_unload_domain ((struct loaded_domain *) runp->data);
Packit bbfece
      runp = runp->next;
Packit bbfece
      free ((char *) here->filename);
Packit bbfece
      free (here);
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
#endif