1 1.1 mrg /* Handle list of needed message catalogs 2 1.1 mrg Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. 3 1.1 mrg Written by Ulrich Drepper <drepper (at) gnu.org>, 1995. 4 1.1 mrg 5 1.1 mrg This program is free software; you can redistribute it and/or modify it 6 1.1 mrg under the terms of the GNU Library General Public License as published 7 1.1 mrg by the Free Software Foundation; either version 2, or (at your option) 8 1.1 mrg any later version. 9 1.1 mrg 10 1.1 mrg This program is distributed in the hope that it will be useful, 11 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 12 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 1.1 mrg Library General Public License for more details. 14 1.1 mrg 15 1.1 mrg You should have received a copy of the GNU Library General Public 16 1.1 mrg License along with this program; if not, write to the Free Software 17 1.1 mrg Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 18 1.1 mrg USA. */ 19 1.1 mrg 20 1.1 mrg #ifdef HAVE_CONFIG_H 21 1.1 mrg # include <config.h> 22 1.1 mrg #endif 23 1.1 mrg 24 1.1 mrg #include <stdio.h> 25 1.1 mrg #include <sys/types.h> 26 1.1 mrg #include <stdlib.h> 27 1.1 mrg #include <string.h> 28 1.1 mrg 29 1.1 mrg #if defined HAVE_UNISTD_H || defined _LIBC 30 1.1 mrg # include <unistd.h> 31 1.1 mrg #endif 32 1.1 mrg 33 1.1 mrg #include "gettextP.h" 34 1.1 mrg #ifdef _LIBC 35 1.1 mrg # include <libintl.h> 36 1.1 mrg #else 37 1.1 mrg # include "libgnuintl.h" 38 1.1 mrg #endif 39 1.1 mrg 40 1.1 mrg /* @@ end of prolog @@ */ 41 1.1 mrg /* List of already loaded domains. */ 42 1.1 mrg static struct loaded_l10nfile *_nl_loaded_domains; 43 1.1 mrg 44 1.1 mrg 45 1.1 mrg /* Return a data structure describing the message catalog described by 46 1.1 mrg the DOMAINNAME and CATEGORY parameters with respect to the currently 47 1.1 mrg established bindings. */ 48 1.1 mrg struct loaded_l10nfile * 49 1.1 mrg internal_function 50 1.1 mrg _nl_find_domain (dirname, locale, domainname, domainbinding) 51 1.1 mrg const char *dirname; 52 1.1 mrg char *locale; 53 1.1 mrg const char *domainname; 54 1.1 mrg struct binding *domainbinding; 55 1.1 mrg { 56 1.1 mrg struct loaded_l10nfile *retval; 57 1.1 mrg const char *language; 58 1.1 mrg const char *modifier; 59 1.1 mrg const char *territory; 60 1.1 mrg const char *codeset; 61 1.1 mrg const char *normalized_codeset; 62 1.1 mrg const char *special; 63 1.1 mrg const char *sponsor; 64 1.1 mrg const char *revision; 65 1.1 mrg const char *alias_value; 66 1.1 mrg int mask; 67 1.1 mrg 68 1.1 mrg /* LOCALE can consist of up to four recognized parts for the XPG syntax: 69 1.1 mrg 70 1.1 mrg language[_territory[.codeset]][@modifier] 71 1.1 mrg 72 1.1 mrg and six parts for the CEN syntax: 73 1.1 mrg 74 1.1 mrg language[_territory][+audience][+special][,[sponsor][_revision]] 75 1.1 mrg 76 1.1 mrg Beside the first part all of them are allowed to be missing. If 77 1.1 mrg the full specified locale is not found, the less specific one are 78 1.1 mrg looked for. The various parts will be stripped off according to 79 1.1 mrg the following order: 80 1.1 mrg (1) revision 81 1.1 mrg (2) sponsor 82 1.1 mrg (3) special 83 1.1 mrg (4) codeset 84 1.1 mrg (5) normalized codeset 85 1.1 mrg (6) territory 86 1.1 mrg (7) audience/modifier 87 1.1 mrg */ 88 1.1 mrg 89 1.1 mrg /* If we have already tested for this locale entry there has to 90 1.1 mrg be one data set in the list of loaded domains. */ 91 1.1 mrg retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, 92 1.1 mrg strlen (dirname) + 1, 0, locale, NULL, NULL, 93 1.1 mrg NULL, NULL, NULL, NULL, NULL, domainname, 0); 94 1.1 mrg if (retval != NULL) 95 1.1 mrg { 96 1.1 mrg /* We know something about this locale. */ 97 1.1 mrg int cnt; 98 1.1 mrg 99 1.1 mrg if (retval->decided == 0) 100 1.1 mrg _nl_load_domain (retval, domainbinding); 101 1.1 mrg 102 1.1 mrg if (retval->data != NULL) 103 1.1 mrg return retval; 104 1.1 mrg 105 1.1 mrg for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) 106 1.1 mrg { 107 1.1 mrg if (retval->successor[cnt]->decided == 0) 108 1.1 mrg _nl_load_domain (retval->successor[cnt], domainbinding); 109 1.1 mrg 110 1.1 mrg if (retval->successor[cnt]->data != NULL) 111 1.1 mrg break; 112 1.1 mrg } 113 1.1 mrg return cnt >= 0 ? retval : NULL; 114 1.1 mrg /* NOTREACHED */ 115 1.1 mrg } 116 1.1 mrg 117 1.1 mrg /* See whether the locale value is an alias. If yes its value 118 1.1 mrg *overwrites* the alias name. No test for the original value is 119 1.1 mrg done. */ 120 1.1 mrg alias_value = _nl_expand_alias (locale); 121 1.1 mrg if (alias_value != NULL) 122 1.1 mrg { 123 1.1 mrg #if defined _LIBC || defined HAVE_STRDUP 124 1.1 mrg locale = strdup (alias_value); 125 1.1 mrg if (locale == NULL) 126 1.1 mrg return NULL; 127 1.1 mrg #else 128 1.1 mrg size_t len = strlen (alias_value) + 1; 129 1.1 mrg locale = (char *) malloc (len); 130 1.1 mrg if (locale == NULL) 131 1.1 mrg return NULL; 132 1.1 mrg 133 1.1 mrg memcpy (locale, alias_value, len); 134 1.1 mrg #endif 135 1.1 mrg } 136 1.1 mrg 137 1.1 mrg /* Now we determine the single parts of the locale name. First 138 1.1 mrg look for the language. Termination symbols are `_' and `@' if 139 1.1 mrg we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ 140 1.1 mrg mask = _nl_explode_name (locale, &language, &modifier, &territory, 141 1.1 mrg &codeset, &normalized_codeset, &special, 142 1.1 mrg &sponsor, &revision); 143 1.1 mrg 144 1.1 mrg /* Create all possible locale entries which might be interested in 145 1.1 mrg generalization. */ 146 1.1 mrg retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, 147 1.1 mrg strlen (dirname) + 1, mask, language, territory, 148 1.1 mrg codeset, normalized_codeset, modifier, special, 149 1.1 mrg sponsor, revision, domainname, 1); 150 1.1 mrg if (retval == NULL) 151 1.1 mrg /* This means we are out of core. */ 152 1.1 mrg return NULL; 153 1.1 mrg 154 1.1 mrg if (retval->decided == 0) 155 1.1 mrg _nl_load_domain (retval, domainbinding); 156 1.1 mrg if (retval->data == NULL) 157 1.1 mrg { 158 1.1 mrg int cnt; 159 1.1 mrg for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) 160 1.1 mrg { 161 1.1 mrg if (retval->successor[cnt]->decided == 0) 162 1.1 mrg _nl_load_domain (retval->successor[cnt], domainbinding); 163 1.1 mrg if (retval->successor[cnt]->data != NULL) 164 1.1 mrg break; 165 1.1 mrg } 166 1.1 mrg } 167 1.1 mrg 168 1.1 mrg /* The room for an alias was dynamically allocated. Free it now. */ 169 1.1 mrg if (alias_value != NULL) 170 1.1 mrg free (locale); 171 1.1 mrg 172 1.1 mrg /* The space for normalized_codeset is dynamically allocated. Free it. */ 173 1.1 mrg if (mask & XPG_NORM_CODESET) 174 1.1 mrg free ((void *) normalized_codeset); 175 1.1 mrg 176 1.1 mrg return retval; 177 1.1 mrg } 178 1.1 mrg 179 1.1 mrg 180 1.1 mrg #ifdef _LIBC 181 1.1 mrg libc_freeres_fn (free_mem) 182 1.1 mrg { 183 1.1 mrg struct loaded_l10nfile *runp = _nl_loaded_domains; 184 1.1 mrg 185 1.1 mrg while (runp != NULL) 186 1.1 mrg { 187 1.1 mrg struct loaded_l10nfile *here = runp; 188 1.1 mrg if (runp->data != NULL) 189 1.1 mrg _nl_unload_domain ((struct loaded_domain *) runp->data); 190 1.1 mrg runp = runp->next; 191 1.1 mrg free ((char *) here->filename); 192 1.1 mrg free (here); 193 1.1 mrg } 194 1.1 mrg } 195 1.1 mrg #endif 196