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