154359Sroberto/*	$NetBSD: finddomain.c,v 1.1.1.1 2016/01/14 00:11:28 christos Exp $	*/
254359Sroberto
354359Sroberto/* Handle list of needed message catalogs
454359Sroberto   Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc.
554359Sroberto   Written by Ulrich Drepper <drepper@gnu.org>, 1995.
654359Sroberto
754359Sroberto   This program is free software; you can redistribute it and/or modify it
854359Sroberto   under the terms of the GNU Library General Public License as published
954359Sroberto   by the Free Software Foundation; either version 2, or (at your option)
1054359Sroberto   any later version.
1154359Sroberto
1254359Sroberto   This program is distributed in the hope that it will be useful,
1354359Sroberto   but WITHOUT ANY WARRANTY; without even the implied warranty of
1454359Sroberto   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1554359Sroberto   Library General Public License for more details.
1654359Sroberto
1754359Sroberto   You should have received a copy of the GNU Library General Public
1854359Sroberto   License along with this program; if not, write to the Free Software
1982498Sroberto   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2082498Sroberto   USA.  */
2154359Sroberto
2254359Sroberto#ifdef HAVE_CONFIG_H
2354359Sroberto# include <config.h>
2454359Sroberto#endif
2554359Sroberto
2654359Sroberto#include <stdio.h>
2754359Sroberto#include <sys/types.h>
2854359Sroberto#include <stdlib.h>
2954359Sroberto#include <string.h>
3054359Sroberto
3154359Sroberto#if defined HAVE_UNISTD_H || defined _LIBC
3254359Sroberto# include <unistd.h>
3354359Sroberto#endif
3454359Sroberto
3554359Sroberto#include "gettextP.h"
3654359Sroberto#ifdef _LIBC
3754359Sroberto# include <libintl.h>
3854359Sroberto#else
3954359Sroberto# include "libgnuintl.h"
4054359Sroberto#endif
4154359Sroberto
4254359Sroberto/* @@ end of prolog @@ */
4354359Sroberto/* List of already loaded domains.  */
4454359Srobertostatic struct loaded_l10nfile *_nl_loaded_domains;
4554359Sroberto
4654359Sroberto
4754359Sroberto/* Return a data structure describing the message catalog described by
4854359Sroberto   the DOMAINNAME and CATEGORY parameters with respect to the currently
4954359Sroberto   established bindings.  */
5054359Srobertostruct loaded_l10nfile *
5154359Srobertointernal_function
5254359Sroberto_nl_find_domain (const char *dirname, char *locale,
5354359Sroberto		 const char *domainname, struct binding *domainbinding)
5454359Sroberto{
5554359Sroberto  struct loaded_l10nfile *retval;
5654359Sroberto  const char *language;
5754359Sroberto  const char *modifier;
5854359Sroberto  const char *territory;
5954359Sroberto  const char *codeset;
6054359Sroberto  const char *normalized_codeset;
6154359Sroberto  const char *special;
6254359Sroberto  const char *sponsor;
6354359Sroberto  const char *revision;
6454359Sroberto  const char *alias_value;
6554359Sroberto  int mask;
6654359Sroberto
6754359Sroberto  /* LOCALE can consist of up to four recognized parts for the XPG syntax:
6854359Sroberto
6954359Sroberto		language[_territory[.codeset]][@modifier]
7054359Sroberto
7154359Sroberto     and six parts for the CEN syntax:
7254359Sroberto
7354359Sroberto	language[_territory][+audience][+special][,[sponsor][_revision]]
7454359Sroberto
7554359Sroberto     Beside the first part all of them are allowed to be missing.  If
7654359Sroberto     the full specified locale is not found, the less specific one are
7754359Sroberto     looked for.  The various parts will be stripped off according to
7854359Sroberto     the following order:
7954359Sroberto		(1) revision
8054359Sroberto		(2) sponsor
8154359Sroberto		(3) special
8254359Sroberto		(4) codeset
8354359Sroberto		(5) normalized codeset
8454359Sroberto		(6) territory
8554359Sroberto		(7) audience/modifier
8654359Sroberto   */
8754359Sroberto
8854359Sroberto  /* If we have already tested for this locale entry there has to
8954359Sroberto     be one data set in the list of loaded domains.  */
9054359Sroberto  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
9154359Sroberto			       strlen (dirname) + 1, 0, locale, NULL, NULL,
9254359Sroberto			       NULL, NULL, NULL, NULL, NULL, domainname, 0);
9354359Sroberto  if (retval != NULL)
9454359Sroberto    {
9554359Sroberto      /* We know something about this locale.  */
9654359Sroberto      int cnt;
9754359Sroberto
9854359Sroberto      if (retval->decided == 0)
9954359Sroberto	_nl_load_domain (retval, domainbinding);
10054359Sroberto
10154359Sroberto      if (retval->data != NULL)
10254359Sroberto	return retval;
10354359Sroberto
10454359Sroberto      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
10554359Sroberto	{
10654359Sroberto	  if (retval->successor[cnt]->decided == 0)
10754359Sroberto	    _nl_load_domain (retval->successor[cnt], domainbinding);
10854359Sroberto
10954359Sroberto	  if (retval->successor[cnt]->data != NULL)
11054359Sroberto	    break;
11154359Sroberto	}
11254359Sroberto      return cnt >= 0 ? retval : NULL;
11354359Sroberto      /* NOTREACHED */
11454359Sroberto    }
11554359Sroberto
11654359Sroberto  /* See whether the locale value is an alias.  If yes its value
11754359Sroberto     *overwrites* the alias name.  No test for the original value is
11854359Sroberto     done.  */
11954359Sroberto  alias_value = _nl_expand_alias (locale);
12054359Sroberto  if (alias_value != NULL)
12154359Sroberto    {
12254359Sroberto#if defined _LIBC || defined HAVE_STRDUP
12354359Sroberto      locale = strdup (alias_value);
12454359Sroberto      if (locale == NULL)
12554359Sroberto	return NULL;
12654359Sroberto#else
12754359Sroberto      size_t len = strlen (alias_value) + 1;
12854359Sroberto      locale = (char *) malloc (len);
12954359Sroberto      if (locale == NULL)
13054359Sroberto	return NULL;
13154359Sroberto
13254359Sroberto      memcpy (locale, alias_value, len);
13354359Sroberto#endif
13454359Sroberto    }
13554359Sroberto
13654359Sroberto  /* Now we determine the single parts of the locale name.  First
13754359Sroberto     look for the language.  Termination symbols are `_' and `@' if
13854359Sroberto     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
13954359Sroberto  mask = _nl_explode_name (locale, &language, &modifier, &territory,
14054359Sroberto			   &codeset, &normalized_codeset, &special,
14154359Sroberto			   &sponsor, &revision);
14254359Sroberto
14354359Sroberto  /* Create all possible locale entries which might be interested in
14454359Sroberto     generalization.  */
14554359Sroberto  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
14654359Sroberto			       strlen (dirname) + 1, mask, language, territory,
14754359Sroberto			       codeset, normalized_codeset, modifier, special,
14854359Sroberto			       sponsor, revision, domainname, 1);
14954359Sroberto  if (retval == NULL)
15054359Sroberto    /* This means we are out of core.  */
15154359Sroberto    return NULL;
15254359Sroberto
15354359Sroberto  if (retval->decided == 0)
15454359Sroberto    _nl_load_domain (retval, domainbinding);
15554359Sroberto  if (retval->data == NULL)
15654359Sroberto    {
15754359Sroberto      int cnt;
15854359Sroberto      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
15954359Sroberto	{
16054359Sroberto	  if (retval->successor[cnt]->decided == 0)
16154359Sroberto	    _nl_load_domain (retval->successor[cnt], domainbinding);
16254359Sroberto	  if (retval->successor[cnt]->data != NULL)
16354359Sroberto	    break;
16454359Sroberto	}
16554359Sroberto    }
16654359Sroberto
16754359Sroberto  /* The room for an alias was dynamically allocated.  Free it now.  */
16854359Sroberto  if (alias_value != NULL)
16954359Sroberto    free (locale);
17054359Sroberto
17154359Sroberto  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
17254359Sroberto  if (mask & XPG_NORM_CODESET)
17354359Sroberto    free ((void *) normalized_codeset);
17454359Sroberto
17554359Sroberto  return retval;
17654359Sroberto}
17754359Sroberto
17854359Sroberto
17954359Sroberto#ifdef _LIBC
18054359Srobertolibc_freeres_fn (free_mem)
18154359Sroberto{
18254359Sroberto  struct loaded_l10nfile *runp = _nl_loaded_domains;
18354359Sroberto
18454359Sroberto  while (runp != NULL)
18554359Sroberto    {
18654359Sroberto      struct loaded_l10nfile *here = runp;
18754359Sroberto      if (runp->data != NULL)
18854359Sroberto	_nl_unload_domain ((struct loaded_domain *) runp->data);
18954359Sroberto      runp = runp->next;
19054359Sroberto      free ((char *) here->filename);
19154359Sroberto      free (here);
19254359Sroberto    }
19354359Sroberto}
19454359Sroberto#endif
19554359Sroberto