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