1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #ifdef HAVE_CONFIG_H
21: # include <config.h>
22: #endif
23:
24: #include <stddef.h>
25: #include <stdlib.h>
26: #include <string.h>
27:
28: #ifdef _LIBC
29: # include <libintl.h>
30: #else
31: # include "libgnuintl.h"
32: #endif
33: #include "gettextP.h"
34:
35: #ifdef _LIBC
36:
37: # include <bits/libc-lock.h>
38: #else
39:
40: # define __libc_rwlock_define(CLASS, NAME)
41: # define __libc_rwlock_wrlock(NAME)
42: # define __libc_rwlock_unlock(NAME)
43: #endif
44:
45:
46:
47:
48: #if !defined _LIBC
49: # define _nl_default_dirname libintl_nl_default_dirname
50: # define _nl_domain_bindings libintl_nl_domain_bindings
51: #endif
52:
53:
54: #ifndef offsetof
55: # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
56: #endif
57:
58:
59:
60:
61: extern const char _nl_default_dirname[];
62: #ifdef _LIBC
63: libc_hidden_proto (_nl_default_dirname)
64: #endif
65:
66:
67: extern struct binding *_nl_domain_bindings;
68:
69:
70: __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
71:
72:
73:
74:
75:
76:
77: #ifdef _LIBC
78: # define BINDTEXTDOMAIN __bindtextdomain
79: # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
80: # ifndef strdup
81: # define strdup(str) __strdup (str)
82: # endif
83: #else
84: # define BINDTEXTDOMAIN libintl_bindtextdomain
85: # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
86: #endif
87:
88:
89: static void set_binding_values PARAMS ((const char *domainname,
90: const char **dirnamep,
91: const char **codesetp));
92:
93:
94:
95:
96:
97:
98:
99: static void
100: set_binding_values (domainname, dirnamep, codesetp)
101: const char *domainname;
102: const char **dirnamep;
103: const char **codesetp;
104: {
105: struct binding *binding;
106: int modified;
107:
108:
109: if (domainname == NULL || domainname[0] == '\0')
110: {
111: if (dirnamep)
112: *dirnamep = NULL;
113: if (codesetp)
114: *codesetp = NULL;
115: return;
116: }
117:
118: __libc_rwlock_wrlock (_nl_state_lock);
119:
120: modified = 0;
121:
122: for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
123: {
124: int compare = strcmp (domainname, binding->domainname);
125: if (compare == 0)
126:
127: break;
128: if (compare < 0)
129: {
130:
131: binding = NULL;
132: break;
133: }
134: }
135:
136: if (binding != NULL)
137: {
138: if (dirnamep)
139: {
140: const char *dirname = *dirnamep;
141:
142: if (dirname == NULL)
143:
144: *dirnamep = binding->dirname;
145: else
146: {
147:
148:
149:
150: char *result = binding->dirname;
151: if (strcmp (dirname, result) != 0)
152: {
153: if (strcmp (dirname, _nl_default_dirname) == 0)
154: result = (char *) _nl_default_dirname;
155: else
156: {
157: #if defined _LIBC || defined HAVE_STRDUP
158: result = strdup (dirname);
159: #else
160: size_t len = strlen (dirname) + 1;
161: result = (char *) malloc (len);
162: if (__builtin_expect (result != NULL, 1))
163: memcpy (result, dirname, len);
164: #endif
165: }
166:
167: if (__builtin_expect (result != NULL, 1))
168: {
169: if (binding->dirname != _nl_default_dirname)
170: free (binding->dirname);
171:
172: binding->dirname = result;
173: modified = 1;
174: }
175: }
176: *dirnamep = result;
177: }
178: }
179:
180: if (codesetp)
181: {
182: const char *codeset = *codesetp;
183:
184: if (codeset == NULL)
185:
186: *codesetp = binding->codeset;
187: else
188: {
189:
190:
191:
192: char *result = binding->codeset;
193: if (result == NULL || strcmp (codeset, result) != 0)
194: {
195: #if defined _LIBC || defined HAVE_STRDUP
196: result = strdup (codeset);
197: #else
198: size_t len = strlen (codeset) + 1;
199: result = (char *) malloc (len);
200: if (__builtin_expect (result != NULL, 1))
201: memcpy (result, codeset, len);
202: #endif
203:
204: if (__builtin_expect (result != NULL, 1))
205: {
206: if (binding->codeset != NULL)
207: free (binding->codeset);
208:
209: binding->codeset = result;
210: modified = 1;
211: }
212: }
213: *codesetp = result;
214: }
215: }
216: }
217: else if ((dirnamep == NULL || *dirnamep == NULL)
218: && (codesetp == NULL || *codesetp == NULL))
219: {
220:
221: if (dirnamep)
222: *dirnamep = _nl_default_dirname;
223: if (codesetp)
224: *codesetp = NULL;
225: }
226: else
227: {
228:
229: size_t len = strlen (domainname) + 1;
230: struct binding *new_binding =
231: (struct binding *) malloc (offsetof (struct binding, domainname) + len);
232:
233: if (__builtin_expect (new_binding == NULL, 0))
234: goto failed;
235:
236: memcpy (new_binding->domainname, domainname, len);
237:
238: if (dirnamep)
239: {
240: const char *dirname = *dirnamep;
241:
242: if (dirname == NULL)
243:
244: dirname = _nl_default_dirname;
245: else
246: {
247: if (strcmp (dirname, _nl_default_dirname) == 0)
248: dirname = _nl_default_dirname;
249: else
250: {
251: char *result;
252: #if defined _LIBC || defined HAVE_STRDUP
253: result = strdup (dirname);
254: if (__builtin_expect (result == NULL, 0))
255: goto failed_dirname;
256: #else
257: size_t len = strlen (dirname) + 1;
258: result = (char *) malloc (len);
259: if (__builtin_expect (result == NULL, 0))
260: goto failed_dirname;
261: memcpy (result, dirname, len);
262: #endif
263: dirname = result;
264: }
265: }
266: *dirnamep = dirname;
267: new_binding->dirname = (char *) dirname;
268: }
269: else
270:
271: new_binding->dirname = (char *) _nl_default_dirname;
272:
273: if (codesetp)
274: {
275: const char *codeset = *codesetp;
276:
277: if (codeset != NULL)
278: {
279: char *result;
280:
281: #if defined _LIBC || defined HAVE_STRDUP
282: result = strdup (codeset);
283: if (__builtin_expect (result == NULL, 0))
284: goto failed_codeset;
285: #else
286: size_t len = strlen (codeset) + 1;
287: result = (char *) malloc (len);
288: if (__builtin_expect (result == NULL, 0))
289: goto failed_codeset;
290: memcpy (result, codeset, len);
291: #endif
292: codeset = result;
293: }
294: *codesetp = codeset;
295: new_binding->codeset = (char *) codeset;
296: }
297: else
298: new_binding->codeset = NULL;
299:
300:
301: if (_nl_domain_bindings == NULL
302: || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
303: {
304: new_binding->next = _nl_domain_bindings;
305: _nl_domain_bindings = new_binding;
306: }
307: else
308: {
309: binding = _nl_domain_bindings;
310: while (binding->next != NULL
311: && strcmp (domainname, binding->next->domainname) > 0)
312: binding = binding->next;
313:
314: new_binding->next = binding->next;
315: binding->next = new_binding;
316: }
317:
318: modified = 1;
319:
320:
321: if (0)
322: {
323: failed_codeset:
324: if (new_binding->dirname != _nl_default_dirname)
325: free (new_binding->dirname);
326: failed_dirname:
327: free (new_binding);
328: failed:
329: if (dirnamep)
330: *dirnamep = NULL;
331: if (codesetp)
332: *codesetp = NULL;
333: }
334: }
335:
336:
337: if (modified)
338: ++_nl_msg_cat_cntr;
339:
340: __libc_rwlock_unlock (_nl_state_lock);
341: }
342:
343:
344:
345: char *
346: BINDTEXTDOMAIN (domainname, dirname)
347: const char *domainname;
348: const char *dirname;
349: {
350: set_binding_values (domainname, &dirname, NULL);
351: return (char *) dirname;
352: }
353:
354:
355:
356: char *
357: BIND_TEXTDOMAIN_CODESET (domainname, codeset)
358: const char *domainname;
359: const char *codeset;
360: {
361: set_binding_values (domainname, NULL, &codeset);
362: return (char *) codeset;
363: }
364:
365: #ifdef _LIBC
366:
367: weak_alias (__bindtextdomain, bindtextdomain);
368: weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
369: #endif