1 /* Implementation of the bindtextdomain(3) function
2 Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28 #include "intl/gettext/libintl.h"
29 #include "intl/gettext/gettextP.h"
30 #include "util/string.h"
32 /* Contains the default location of the message catalogs. */
33 extern const unsigned char _nl_default_dirname__
[];
35 /* List with bindings of specific domains. */
36 extern struct binding
*_nl_domain_bindings__
;
38 /* Prototypes for local functions. */
39 static void set_binding_values(const unsigned char *domainname
,
40 const unsigned char **dirnamep
,
41 const unsigned char **codesetp
);
43 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
44 to be used for the DOMAINNAME message catalog.
45 If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
46 modified, only the current value is returned.
47 If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
48 modified nor returned. */
50 set_binding_values(const unsigned char *domainname
,
51 const unsigned char **dirnamep
,
52 const unsigned char **codesetp
)
54 struct binding
*binding
;
57 /* Some sanity checks. */
58 if (domainname
== NULL
|| domainname
[0] == '\0') {
68 for (binding
= _nl_domain_bindings__
; binding
!= NULL
;
69 binding
= binding
->next
) {
70 int compare
= strcmp(domainname
, binding
->domainname
);
76 /* It is not in the list. */
82 if (binding
!= NULL
) {
84 const unsigned char *dirname
= *dirnamep
;
87 /* The current binding has be to returned. */
88 *dirnamep
= binding
->dirname
;
90 /* The domain is already bound. If the new value and the old
91 one are equal we simply do nothing. Otherwise replace the
93 unsigned char *result
= binding
->dirname
;
95 if (strcmp(dirname
, result
) != 0) {
96 if (strcmp(dirname
, _nl_default_dirname__
)
98 result
= (unsigned char *)
99 _nl_default_dirname__
;
101 result
= strdup(dirname
);
104 if (result
!= NULL
) {
105 if (binding
->dirname
!=
106 _nl_default_dirname__
)
107 free(binding
->dirname
);
109 binding
->dirname
= result
;
118 const unsigned char *codeset
= *codesetp
;
121 /* The current binding has be to returned. */
122 *codesetp
= binding
->codeset
;
124 /* The domain is already bound. If the new value and the old
125 one are equal we simply do nothing. Otherwise replace the
127 unsigned char *result
= binding
->codeset
;
130 || strcmp(codeset
, result
) != 0) {
131 result
= strdup(codeset
);
133 if (result
!= NULL
) {
134 if (binding
->codeset
!= NULL
)
135 free(binding
->codeset
);
137 binding
->codeset
= result
;
138 binding
->codeset_cntr
++;
145 } else if ((dirnamep
== NULL
|| *dirnamep
== NULL
)
146 && (codesetp
== NULL
|| *codesetp
== NULL
)) {
147 /* Simply return the default values. */
149 *dirnamep
= _nl_default_dirname__
;
153 /* We have to create a new binding. */
154 size_t len
= strlen(domainname
) + 1;
155 struct binding
*new_binding
=
157 malloc(offsetof(struct binding
, domainname
) + len
);
159 if (new_binding
== NULL
)
162 memcpy(new_binding
->domainname
, domainname
, len
);
165 const unsigned char *dirname
= *dirnamep
;
168 /* The default value. */
169 dirname
= _nl_default_dirname__
;
171 if (strcmp(dirname
, _nl_default_dirname__
) == 0)
172 dirname
= _nl_default_dirname__
;
174 unsigned char *result
;
176 result
= strdup(dirname
);
183 new_binding
->dirname
= (unsigned char *) dirname
;
185 /* The default value. */
186 new_binding
->dirname
= (unsigned char *) _nl_default_dirname__
;
188 new_binding
->codeset_cntr
= 0;
191 const unsigned char *codeset
= *codesetp
;
193 if (codeset
!= NULL
) {
194 unsigned char *result
;
196 result
= strdup(codeset
);
200 new_binding
->codeset_cntr
++;
203 new_binding
->codeset
= (unsigned char *) codeset
;
205 new_binding
->codeset
= NULL
;
207 /* Now enqueue it. */
208 if (_nl_domain_bindings__
== NULL
209 || strcmp(domainname
, _nl_domain_bindings__
->domainname
) < 0)
211 new_binding
->next
= _nl_domain_bindings__
;
212 _nl_domain_bindings__
= new_binding
;
214 binding
= _nl_domain_bindings__
;
215 while (binding
->next
!= NULL
216 && strcmp(domainname
,
217 binding
->next
->domainname
) > 0)
218 binding
= binding
->next
;
220 new_binding
->next
= binding
->next
;
221 binding
->next
= new_binding
;
226 /* Here we deal with memory allocation failures. */
229 if (new_binding
->dirname
!= _nl_default_dirname__
)
230 free(new_binding
->dirname
);
241 /* If we modified any binding, we flush the caches. */
247 /* Specify that the DOMAINNAME message catalog will be found
248 in DIRNAME rather than in the system locale data base. */
250 bindtextdomain__(const unsigned char *domainname
, const unsigned char *dirname
)
252 set_binding_values(domainname
, &dirname
, NULL
);
253 return (unsigned char *) dirname
;
256 /* Specify the character encoding in which the messages from the
257 DOMAINNAME message catalog will be returned. */
259 bind_textdomain_codeset__(const unsigned char *domainname
, const unsigned char *codeset
)
261 set_binding_values(domainname
, NULL
, &codeset
);
262 return (unsigned char *) codeset
;