15bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Handle list of needed message catalogs
2b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o   Copyright (C) 1995-1999, 2000-2001, 2003 Free Software Foundation, Inc.
3a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   Written by Ulrich Drepper <drepper@gnu.org>, 1995.
45bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
5a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   This program is free software; you can redistribute it and/or modify it
6a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   under the terms of the GNU Library General Public License as published
7a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   by the Free Software Foundation; either version 2, or (at your option)
85bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   any later version.
95bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   This program is distributed in the hope that it will be useful,
115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   but WITHOUT ANY WARRANTY; without even the implied warranty of
12a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   Library General Public License for more details.
145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
15a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   You should have received a copy of the GNU Library General Public
16a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   License along with this program; if not, write to the Free Software
17a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o   USA.  */
195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef HAVE_CONFIG_H
215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <config.h>
225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <stdio.h>
255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include <sys/types.h>
26a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <stdlib.h>
27a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o#include <string.h>
285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if defined HAVE_UNISTD_H || defined _LIBC
305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <unistd.h>
315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#include "gettextP.h"
345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC
355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o# include <libintl.h>
365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else
37a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o# include "libgnuintl.h"
385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* @@ end of prolog @@ */
415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* List of already loaded domains.  */
425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostatic struct loaded_l10nfile *_nl_loaded_domains;
435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o/* Return a data structure describing the message catalog described by
465bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   the DOMAINNAME and CATEGORY parameters with respect to the currently
475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   established bindings.  */
485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ostruct loaded_l10nfile *
495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'ointernal_function
50b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o_nl_find_domain (const char *dirname, char *locale,
51b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'o		 const char *domainname, struct binding *domainbinding)
525bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  struct loaded_l10nfile *retval;
545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *language;
555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *modifier;
565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *territory;
575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *codeset;
585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *normalized_codeset;
595bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *special;
605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *sponsor;
615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *revision;
625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  const char *alias_value;
635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  int mask;
645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* LOCALE can consist of up to four recognized parts for the XPG syntax:
665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		language[_territory[.codeset]][@modifier]
685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
695bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     and six parts for the CEN syntax:
705bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
715bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	language[_territory][+audience][+special][,[sponsor][_revision]]
725bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     Beside the first part all of them are allowed to be missing.  If
745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     the full specified locale is not found, the less specific one are
755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     looked for.  The various parts will be stripped off according to
765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     the following order:
775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		(1) revision
785bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		(2) sponsor
795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		(3) special
805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		(4) codeset
815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		(5) normalized codeset
825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		(6) territory
835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o		(7) audience/modifier
845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o   */
855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* If we have already tested for this locale entry there has to
875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     be one data set in the list of loaded domains.  */
885bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			       strlen (dirname) + 1, 0, locale, NULL, NULL,
905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			       NULL, NULL, NULL, NULL, NULL, domainname, 0);
915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (retval != NULL)
925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
935bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      /* We know something about this locale.  */
945bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      int cnt;
955bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
965bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (retval->decided == 0)
97a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	_nl_load_domain (retval, domainbinding);
985bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
995bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (retval->data != NULL)
1005bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	return retval;
1015bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1025bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
1035bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	{
1045bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  if (retval->successor[cnt]->decided == 0)
105a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	    _nl_load_domain (retval->successor[cnt], domainbinding);
1065bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1075bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  if (retval->successor[cnt]->data != NULL)
1085bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    break;
1095bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	}
1105bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      return cnt >= 0 ? retval : NULL;
1115bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      /* NOTREACHED */
1125bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1135bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1145bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* See whether the locale value is an alias.  If yes its value
1155bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     *overwrites* the alias name.  No test for the original value is
1165bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     done.  */
1175bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  alias_value = _nl_expand_alias (locale);
1185bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (alias_value != NULL)
1195bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1205bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#if defined _LIBC || defined HAVE_STRDUP
1215bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      locale = strdup (alias_value);
1225bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (locale == NULL)
1235bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	return NULL;
1245bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#else
1255bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      size_t len = strlen (alias_value) + 1;
1265bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      locale = (char *) malloc (len);
1275bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (locale == NULL)
1285bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	return NULL;
1295bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1305bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      memcpy (locale, alias_value, len);
1315bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
1325bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1335bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1345bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* Now we determine the single parts of the locale name.  First
1355bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     look for the language.  Termination symbols are `_' and `@' if
1365bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
1375bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  mask = _nl_explode_name (locale, &language, &modifier, &territory,
1385bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			   &codeset, &normalized_codeset, &special,
1395bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			   &sponsor, &revision);
1405bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1415bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* Create all possible locale entries which might be interested in
1425bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o     generalization.  */
1435bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
1445bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			       strlen (dirname) + 1, mask, language, territory,
1455bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			       codeset, normalized_codeset, modifier, special,
1465bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o			       sponsor, revision, domainname, 1);
1475bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (retval == NULL)
1485bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    /* This means we are out of core.  */
1495bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    return NULL;
1505bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1515bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (retval->decided == 0)
152a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    _nl_load_domain (retval, domainbinding);
1535bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (retval->data == NULL)
1545bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1555bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      int cnt;
1565bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
1575bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	{
1585bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  if (retval->successor[cnt]->decided == 0)
159a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o	    _nl_load_domain (retval->successor[cnt], domainbinding);
1605bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	  if (retval->successor[cnt]->data != NULL)
1615bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	    break;
1625bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	}
1635bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1645bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1655bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  /* The room for an alias was dynamically allocated.  Free it now.  */
1665bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  if (alias_value != NULL)
1675bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    free (locale);
1685bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
169a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
170a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o  if (mask & XPG_NORM_CODESET)
171a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o    free ((void *) normalized_codeset);
172a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o
1735bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  return retval;
1745bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
1755bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1765bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1775bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#ifdef _LIBC
178b0cacab066000b940551d59aad3e4553d4bad268Theodore Ts'olibc_freeres_fn (free_mem)
1795bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o{
1805bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  struct loaded_l10nfile *runp = _nl_loaded_domains;
1815bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o
1825bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o  while (runp != NULL)
1835bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    {
1845bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      struct loaded_l10nfile *here = runp;
1855bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      if (runp->data != NULL)
1865bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o	_nl_unload_domain ((struct loaded_domain *) runp->data);
1875bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      runp = runp->next;
188a04eba3f8868af1d9b7b504d3d430c55ed3dc777Theodore Ts'o      free ((char *) here->filename);
1895bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o      free (here);
1905bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o    }
1915bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o}
1925bc5a89c2a5c07b0237c13d37d869c986b5435fbTheodore Ts'o#endif
193