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