Back to index

glibc  2.9
finddomain.c
Go to the documentation of this file.
00001 /* Handle list of needed message catalogs
00002    Copyright (C) 1995-1999, 2000, 2001, 2002, 2004, 2006, 2007
00003    Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Written by Ulrich Drepper <drepper@gnu.org>, 1995.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 # include <config.h>
00024 #endif
00025 
00026 #include <stdio.h>
00027 #include <sys/types.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 
00031 #if defined HAVE_UNISTD_H || defined _LIBC
00032 # include <unistd.h>
00033 #endif
00034 
00035 #include "gettextP.h"
00036 #ifdef _LIBC
00037 # include <libintl.h>
00038 # include <bits/libc-lock.h>
00039 #else
00040 # include "libgnuintl.h"
00041 #endif
00042 
00043 /* @@ end of prolog @@ */
00044 /* List of already loaded domains.  */
00045 static struct loaded_l10nfile *_nl_loaded_domains;
00046 
00047 
00048 /* Return a data structure describing the message catalog described by
00049    the DOMAINNAME and CATEGORY parameters with respect to the currently
00050    established bindings.  */
00051 struct loaded_l10nfile *
00052 internal_function
00053 _nl_find_domain (dirname, locale, domainname, domainbinding)
00054      const char *dirname;
00055      char *locale;
00056      const char *domainname;
00057      struct binding *domainbinding;
00058 {
00059   struct loaded_l10nfile *retval;
00060   const char *language;
00061   const char *modifier;
00062   const char *territory;
00063   const char *codeset;
00064   const char *normalized_codeset;
00065   const char *alias_value;
00066   int mask;
00067 
00068   /* LOCALE can consist of up to four recognized parts for the XPG syntax:
00069 
00070               language[_territory[.codeset]][@modifier]
00071 
00072      Beside the first part all of them are allowed to be missing.  If
00073      the full specified locale is not found, the less specific one are
00074      looked for.  The various parts will be stripped off according to
00075      the following order:
00076               (1) codeset
00077               (2) normalized codeset
00078               (3) territory
00079               (4) modifier
00080    */
00081 
00082   /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
00083   __libc_rwlock_define_initialized (static, lock);
00084   __libc_rwlock_rdlock (lock);
00085 
00086   /* If we have already tested for this locale entry there has to
00087      be one data set in the list of loaded domains.  */
00088   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
00089                             strlen (dirname) + 1, 0, locale, NULL, NULL,
00090                             NULL, NULL, domainname, 0);
00091   __libc_rwlock_unlock (lock);
00092 
00093   if (retval != NULL)
00094     {
00095       /* We know something about this locale.  */
00096       int cnt;
00097 
00098       if (retval->decided <= 0)
00099        _nl_load_domain (retval, domainbinding);
00100 
00101       if (retval->data != NULL)
00102        return retval;
00103 
00104       for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
00105        {
00106          if (retval->successor[cnt]->decided <= 0)
00107            _nl_load_domain (retval->successor[cnt], domainbinding);
00108 
00109          if (retval->successor[cnt]->data != NULL)
00110            break;
00111        }
00112 
00113       return retval;
00114       /* NOTREACHED */
00115     }
00116 
00117   /* See whether the locale value is an alias.  If yes its value
00118      *overwrites* the alias name.  No test for the original value is
00119      done.  */
00120   alias_value = _nl_expand_alias (locale);
00121   if (alias_value != NULL)
00122     locale = strdupa (alias_value);
00123 
00124   /* Now we determine the single parts of the locale name.  First
00125      look for the language.  Termination symbols are `_' and `@' if
00126      we use XPG4 style, and `_', `+', and `,' if we use CEN syntax.  */
00127   mask = _nl_explode_name (locale, &language, &modifier, &territory,
00128                         &codeset, &normalized_codeset);
00129   if (mask == -1)
00130     /* This means we are out of core.  */
00131     return NULL;
00132 
00133   /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
00134   __libc_rwlock_wrlock (lock);
00135 
00136   /* Create all possible locale entries which might be interested in
00137      generalization.  */
00138   retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
00139                             strlen (dirname) + 1, mask, language, territory,
00140                             codeset, normalized_codeset, modifier,
00141                             domainname, 1);
00142   __libc_rwlock_unlock (lock);
00143 
00144   if (retval == NULL)
00145     /* This means we are out of core.  */
00146     goto out;
00147 
00148   if (retval->decided <= 0)
00149     _nl_load_domain (retval, domainbinding);
00150   if (retval->data == NULL)
00151     {
00152       int cnt;
00153       for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
00154        {
00155          if (retval->successor[cnt]->decided <= 0)
00156            _nl_load_domain (retval->successor[cnt], domainbinding);
00157          if (retval->successor[cnt]->data != NULL)
00158            break;
00159        }
00160     }
00161 
00162 out:
00163   /* The space for normalized_codeset is dynamically allocated.  Free it.  */
00164   if (mask & XPG_NORM_CODESET)
00165     free ((void *) normalized_codeset);
00166 
00167   return retval;
00168 }
00169 
00170 
00171 #ifdef _LIBC
00172 /* This is called from iconv/gconv_db.c's free_mem, as locales must
00173    be freed before freeing gconv steps arrays.  */
00174 void __libc_freeres_fn_section
00175 _nl_finddomain_subfreeres ()
00176 {
00177   struct loaded_l10nfile *runp = _nl_loaded_domains;
00178 
00179   while (runp != NULL)
00180     {
00181       struct loaded_l10nfile *here = runp;
00182       if (runp->data != NULL)
00183        _nl_unload_domain ((struct loaded_domain *) runp->data);
00184       runp = runp->next;
00185       free ((char *) here->filename);
00186       free (here);
00187     }
00188 }
00189 #endif