xref: /openbsd-src/gnu/usr.bin/binutils-2.17/intl/bindtextdom.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* Implementation of the bindtextdomain(3) function
2*3d8817e4Smiod    Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
3*3d8817e4Smiod 
4*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify
5*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
6*3d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
7*3d8817e4Smiod    any later version.
8*3d8817e4Smiod 
9*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
10*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
11*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*3d8817e4Smiod    GNU General Public License for more details.
13*3d8817e4Smiod 
14*3d8817e4Smiod    You should have received a copy of the GNU General Public License
15*3d8817e4Smiod    along with this program; if not, write to the Free Software Foundation,
16*3d8817e4Smiod    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
17*3d8817e4Smiod 
18*3d8817e4Smiod #ifdef HAVE_CONFIG_H
19*3d8817e4Smiod # include <config.h>
20*3d8817e4Smiod #endif
21*3d8817e4Smiod 
22*3d8817e4Smiod #if defined STDC_HEADERS || defined _LIBC
23*3d8817e4Smiod # include <stdlib.h>
24*3d8817e4Smiod #else
25*3d8817e4Smiod # ifdef HAVE_MALLOC_H
26*3d8817e4Smiod #  include <malloc.h>
27*3d8817e4Smiod # else
28*3d8817e4Smiod void free ();
29*3d8817e4Smiod # endif
30*3d8817e4Smiod #endif
31*3d8817e4Smiod 
32*3d8817e4Smiod #if defined HAVE_STRING_H || defined _LIBC
33*3d8817e4Smiod # include <string.h>
34*3d8817e4Smiod #else
35*3d8817e4Smiod # include <strings.h>
36*3d8817e4Smiod # ifndef memcpy
37*3d8817e4Smiod #  define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
38*3d8817e4Smiod # endif
39*3d8817e4Smiod #endif
40*3d8817e4Smiod 
41*3d8817e4Smiod #ifdef _LIBC
42*3d8817e4Smiod # include <libintl.h>
43*3d8817e4Smiod #else
44*3d8817e4Smiod # include "libgettext.h"
45*3d8817e4Smiod #endif
46*3d8817e4Smiod #include "gettext.h"
47*3d8817e4Smiod #include "gettextP.h"
48*3d8817e4Smiod 
49*3d8817e4Smiod /* @@ end of prolog @@ */
50*3d8817e4Smiod 
51*3d8817e4Smiod /* Contains the default location of the message catalogs.  */
52*3d8817e4Smiod extern const char _nl_default_dirname[];
53*3d8817e4Smiod 
54*3d8817e4Smiod /* List with bindings of specific domains.  */
55*3d8817e4Smiod extern struct binding *_nl_domain_bindings;
56*3d8817e4Smiod 
57*3d8817e4Smiod 
58*3d8817e4Smiod /* Names for the libintl functions are a problem.  They must not clash
59*3d8817e4Smiod    with existing names and they should follow ANSI C.  But this source
60*3d8817e4Smiod    code is also used in GNU C Library where the names have a __
61*3d8817e4Smiod    prefix.  So we have to make a difference here.  */
62*3d8817e4Smiod #ifdef _LIBC
63*3d8817e4Smiod # define BINDTEXTDOMAIN __bindtextdomain
64*3d8817e4Smiod # ifndef strdup
65*3d8817e4Smiod #  define strdup(str) __strdup (str)
66*3d8817e4Smiod # endif
67*3d8817e4Smiod #else
68*3d8817e4Smiod # define BINDTEXTDOMAIN bindtextdomain__
69*3d8817e4Smiod #endif
70*3d8817e4Smiod 
71*3d8817e4Smiod /* Specify that the DOMAINNAME message catalog will be found
72*3d8817e4Smiod    in DIRNAME rather than in the system locale data base.  */
73*3d8817e4Smiod char *
BINDTEXTDOMAIN(domainname,dirname)74*3d8817e4Smiod BINDTEXTDOMAIN (domainname, dirname)
75*3d8817e4Smiod      const char *domainname;
76*3d8817e4Smiod      const char *dirname;
77*3d8817e4Smiod {
78*3d8817e4Smiod   struct binding *binding;
79*3d8817e4Smiod 
80*3d8817e4Smiod   /* Some sanity checks.  */
81*3d8817e4Smiod   if (domainname == NULL || domainname[0] == '\0')
82*3d8817e4Smiod     return NULL;
83*3d8817e4Smiod 
84*3d8817e4Smiod   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
85*3d8817e4Smiod     {
86*3d8817e4Smiod       int compare = strcmp (domainname, binding->domainname);
87*3d8817e4Smiod       if (compare == 0)
88*3d8817e4Smiod 	/* We found it!  */
89*3d8817e4Smiod 	break;
90*3d8817e4Smiod       if (compare < 0)
91*3d8817e4Smiod 	{
92*3d8817e4Smiod 	  /* It is not in the list.  */
93*3d8817e4Smiod 	  binding = NULL;
94*3d8817e4Smiod 	  break;
95*3d8817e4Smiod 	}
96*3d8817e4Smiod     }
97*3d8817e4Smiod 
98*3d8817e4Smiod   if (dirname == NULL)
99*3d8817e4Smiod     /* The current binding has be to returned.  */
100*3d8817e4Smiod     return binding == NULL ? (char *) _nl_default_dirname : binding->dirname;
101*3d8817e4Smiod 
102*3d8817e4Smiod   if (binding != NULL)
103*3d8817e4Smiod     {
104*3d8817e4Smiod       /* The domain is already bound.  If the new value and the old
105*3d8817e4Smiod 	 one are equal we simply do nothing.  Otherwise replace the
106*3d8817e4Smiod 	 old binding.  */
107*3d8817e4Smiod       if (strcmp (dirname, binding->dirname) != 0)
108*3d8817e4Smiod 	{
109*3d8817e4Smiod 	  char *new_dirname;
110*3d8817e4Smiod 
111*3d8817e4Smiod 	  if (strcmp (dirname, _nl_default_dirname) == 0)
112*3d8817e4Smiod 	    new_dirname = (char *) _nl_default_dirname;
113*3d8817e4Smiod 	  else
114*3d8817e4Smiod 	    {
115*3d8817e4Smiod #if defined _LIBC || defined HAVE_STRDUP
116*3d8817e4Smiod 	      new_dirname = strdup (dirname);
117*3d8817e4Smiod 	      if (new_dirname == NULL)
118*3d8817e4Smiod 		return NULL;
119*3d8817e4Smiod #else
120*3d8817e4Smiod 	      size_t len = strlen (dirname) + 1;
121*3d8817e4Smiod 	      new_dirname = (char *) malloc (len);
122*3d8817e4Smiod 	      if (new_dirname == NULL)
123*3d8817e4Smiod 		return NULL;
124*3d8817e4Smiod 
125*3d8817e4Smiod 	      memcpy (new_dirname, dirname, len);
126*3d8817e4Smiod #endif
127*3d8817e4Smiod 	    }
128*3d8817e4Smiod 
129*3d8817e4Smiod 	  if (binding->dirname != _nl_default_dirname)
130*3d8817e4Smiod 	    free (binding->dirname);
131*3d8817e4Smiod 
132*3d8817e4Smiod 	  binding->dirname = new_dirname;
133*3d8817e4Smiod 	}
134*3d8817e4Smiod     }
135*3d8817e4Smiod   else
136*3d8817e4Smiod     {
137*3d8817e4Smiod       /* We have to create a new binding.  */
138*3d8817e4Smiod #if !defined _LIBC && !defined HAVE_STRDUP
139*3d8817e4Smiod       size_t len;
140*3d8817e4Smiod #endif
141*3d8817e4Smiod       struct binding *new_binding =
142*3d8817e4Smiod 	(struct binding *) malloc (sizeof (*new_binding));
143*3d8817e4Smiod 
144*3d8817e4Smiod       if (new_binding == NULL)
145*3d8817e4Smiod 	return NULL;
146*3d8817e4Smiod 
147*3d8817e4Smiod #if defined _LIBC || defined HAVE_STRDUP
148*3d8817e4Smiod       new_binding->domainname = strdup (domainname);
149*3d8817e4Smiod       if (new_binding->domainname == NULL)
150*3d8817e4Smiod 	return NULL;
151*3d8817e4Smiod #else
152*3d8817e4Smiod       len = strlen (domainname) + 1;
153*3d8817e4Smiod       new_binding->domainname = (char *) malloc (len);
154*3d8817e4Smiod       if (new_binding->domainname == NULL)
155*3d8817e4Smiod 	return NULL;
156*3d8817e4Smiod       memcpy (new_binding->domainname, domainname, len);
157*3d8817e4Smiod #endif
158*3d8817e4Smiod 
159*3d8817e4Smiod       if (strcmp (dirname, _nl_default_dirname) == 0)
160*3d8817e4Smiod 	new_binding->dirname = (char *) _nl_default_dirname;
161*3d8817e4Smiod       else
162*3d8817e4Smiod 	{
163*3d8817e4Smiod #if defined _LIBC || defined HAVE_STRDUP
164*3d8817e4Smiod 	  new_binding->dirname = strdup (dirname);
165*3d8817e4Smiod 	  if (new_binding->dirname == NULL)
166*3d8817e4Smiod 	    return NULL;
167*3d8817e4Smiod #else
168*3d8817e4Smiod 	  len = strlen (dirname) + 1;
169*3d8817e4Smiod 	  new_binding->dirname = (char *) malloc (len);
170*3d8817e4Smiod 	  if (new_binding->dirname == NULL)
171*3d8817e4Smiod 	    return NULL;
172*3d8817e4Smiod 	  memcpy (new_binding->dirname, dirname, len);
173*3d8817e4Smiod #endif
174*3d8817e4Smiod 	}
175*3d8817e4Smiod 
176*3d8817e4Smiod       /* Now enqueue it.  */
177*3d8817e4Smiod       if (_nl_domain_bindings == NULL
178*3d8817e4Smiod 	  || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
179*3d8817e4Smiod 	{
180*3d8817e4Smiod 	  new_binding->next = _nl_domain_bindings;
181*3d8817e4Smiod 	  _nl_domain_bindings = new_binding;
182*3d8817e4Smiod 	}
183*3d8817e4Smiod       else
184*3d8817e4Smiod 	{
185*3d8817e4Smiod 	  binding = _nl_domain_bindings;
186*3d8817e4Smiod 	  while (binding->next != NULL
187*3d8817e4Smiod 		 && strcmp (domainname, binding->next->domainname) > 0)
188*3d8817e4Smiod 	    binding = binding->next;
189*3d8817e4Smiod 
190*3d8817e4Smiod 	  new_binding->next = binding->next;
191*3d8817e4Smiod 	  binding->next = new_binding;
192*3d8817e4Smiod 	}
193*3d8817e4Smiod 
194*3d8817e4Smiod       binding = new_binding;
195*3d8817e4Smiod     }
196*3d8817e4Smiod 
197*3d8817e4Smiod   return binding->dirname;
198*3d8817e4Smiod }
199*3d8817e4Smiod 
200*3d8817e4Smiod #ifdef _LIBC
201*3d8817e4Smiod /* Alias for function name in GNU C Library.  */
202*3d8817e4Smiod weak_alias (__bindtextdomain, bindtextdomain);
203*3d8817e4Smiod #endif
204