Back to index

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