00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #include <stddef.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026
00027 #ifdef _LIBC
00028 # include <libintl.h>
00029 #else
00030 # include "libgnuintl.h"
00031 #endif
00032 #include "gettextP.h"
00033
00034 #ifdef _LIBC
00035
00036 # include <bits/libc-lock.h>
00037 #else
00038
00039 # define __libc_rwlock_define(CLASS, NAME)
00040 # define __libc_rwlock_wrlock(NAME)
00041 # define __libc_rwlock_unlock(NAME)
00042 #endif
00043
00044
00045
00046
00047 #if !defined _LIBC
00048 # define _nl_default_dirname libintl_nl_default_dirname
00049 # define _nl_domain_bindings libintl_nl_domain_bindings
00050 #endif
00051
00052
00053 #ifndef offsetof
00054 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
00055 #endif
00056
00057
00058
00059
00060 extern const char _nl_default_dirname[];
00061 #ifdef _LIBC
00062 extern const char _nl_default_dirname_internal[] attribute_hidden;
00063 #else
00064 # define INTUSE(name) name
00065 #endif
00066
00067
00068 extern struct binding *_nl_domain_bindings;
00069
00070
00071 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
00072
00073
00074
00075
00076
00077
00078 #ifdef _LIBC
00079 # define BINDTEXTDOMAIN __bindtextdomain
00080 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
00081 # ifndef strdup
00082 # define strdup(str) __strdup (str)
00083 # endif
00084 #else
00085 # define BINDTEXTDOMAIN libintl_bindtextdomain
00086 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
00087 #endif
00088
00089
00090 static void set_binding_values PARAMS ((const char *domainname,
00091 const char **dirnamep,
00092 const char **codesetp));
00093
00094
00095
00096
00097
00098
00099
00100 static void
00101 set_binding_values (domainname, dirnamep, codesetp)
00102 const char *domainname;
00103 const char **dirnamep;
00104 const char **codesetp;
00105 {
00106 struct binding *binding;
00107 int modified;
00108
00109
00110 if (domainname == NULL || domainname[0] == '\0')
00111 {
00112 if (dirnamep)
00113 *dirnamep = NULL;
00114 if (codesetp)
00115 *codesetp = NULL;
00116 return;
00117 }
00118
00119 __libc_rwlock_wrlock (_nl_state_lock);
00120
00121 modified = 0;
00122
00123 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
00124 {
00125 int compare = strcmp (domainname, binding->domainname);
00126 if (compare == 0)
00127
00128 break;
00129 if (compare < 0)
00130 {
00131
00132 binding = NULL;
00133 break;
00134 }
00135 }
00136
00137 if (binding != NULL)
00138 {
00139 if (dirnamep)
00140 {
00141 const char *dirname = *dirnamep;
00142
00143 if (dirname == NULL)
00144
00145 *dirnamep = binding->dirname;
00146 else
00147 {
00148
00149
00150
00151 char *result = binding->dirname;
00152 if (strcmp (dirname, result) != 0)
00153 {
00154 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
00155 result = (char *) INTUSE(_nl_default_dirname);
00156 else
00157 {
00158 #if defined _LIBC || defined HAVE_STRDUP
00159 result = strdup (dirname);
00160 #else
00161 size_t len = strlen (dirname) + 1;
00162 result = (char *) malloc (len);
00163 if (__builtin_expect (result != NULL, 1))
00164 memcpy (result, dirname, len);
00165 #endif
00166 }
00167
00168 if (__builtin_expect (result != NULL, 1))
00169 {
00170 if (binding->dirname != INTUSE(_nl_default_dirname))
00171 free (binding->dirname);
00172
00173 binding->dirname = result;
00174 modified = 1;
00175 }
00176 }
00177 *dirnamep = result;
00178 }
00179 }
00180
00181 if (codesetp)
00182 {
00183 const char *codeset = *codesetp;
00184
00185 if (codeset == NULL)
00186
00187 *codesetp = binding->codeset;
00188 else
00189 {
00190
00191
00192
00193 char *result = binding->codeset;
00194 if (result == NULL || strcmp (codeset, result) != 0)
00195 {
00196 #if defined _LIBC || defined HAVE_STRDUP
00197 result = strdup (codeset);
00198 #else
00199 size_t len = strlen (codeset) + 1;
00200 result = (char *) malloc (len);
00201 if (__builtin_expect (result != NULL, 1))
00202 memcpy (result, codeset, len);
00203 #endif
00204
00205 if (__builtin_expect (result != NULL, 1))
00206 {
00207 if (binding->codeset != NULL)
00208 free (binding->codeset);
00209
00210 binding->codeset = result;
00211 binding->codeset_cntr++;
00212 modified = 1;
00213 }
00214 }
00215 *codesetp = result;
00216 }
00217 }
00218 }
00219 else if ((dirnamep == NULL || *dirnamep == NULL)
00220 && (codesetp == NULL || *codesetp == NULL))
00221 {
00222
00223 if (dirnamep)
00224 *dirnamep = INTUSE(_nl_default_dirname);
00225 if (codesetp)
00226 *codesetp = NULL;
00227 }
00228 else
00229 {
00230
00231 size_t len = strlen (domainname) + 1;
00232 struct binding *new_binding =
00233 (struct binding *) malloc (offsetof (struct binding, domainname) + len);
00234
00235 if (__builtin_expect (new_binding == NULL, 0))
00236 goto failed;
00237
00238 memcpy (new_binding->domainname, domainname, len);
00239
00240 if (dirnamep)
00241 {
00242 const char *dirname = *dirnamep;
00243
00244 if (dirname == NULL)
00245
00246 dirname = INTUSE(_nl_default_dirname);
00247 else
00248 {
00249 if (strcmp (dirname, INTUSE(_nl_default_dirname)) == 0)
00250 dirname = INTUSE(_nl_default_dirname);
00251 else
00252 {
00253 char *result;
00254 #if defined _LIBC || defined HAVE_STRDUP
00255 result = strdup (dirname);
00256 if (__builtin_expect (result == NULL, 0))
00257 goto failed_dirname;
00258 #else
00259 size_t len = strlen (dirname) + 1;
00260 result = (char *) malloc (len);
00261 if (__builtin_expect (result == NULL, 0))
00262 goto failed_dirname;
00263 memcpy (result, dirname, len);
00264 #endif
00265 dirname = result;
00266 }
00267 }
00268 *dirnamep = dirname;
00269 new_binding->dirname = (char *) dirname;
00270 }
00271 else
00272
00273 new_binding->dirname = (char *) INTUSE(_nl_default_dirname);
00274
00275 new_binding->codeset_cntr = 0;
00276
00277 if (codesetp)
00278 {
00279 const char *codeset = *codesetp;
00280
00281 if (codeset != NULL)
00282 {
00283 char *result;
00284
00285 #if defined _LIBC || defined HAVE_STRDUP
00286 result = strdup (codeset);
00287 if (__builtin_expect (result == NULL, 0))
00288 goto failed_codeset;
00289 #else
00290 size_t len = strlen (codeset) + 1;
00291 result = (char *) malloc (len);
00292 if (__builtin_expect (result == NULL, 0))
00293 goto failed_codeset;
00294 memcpy (result, codeset, len);
00295 #endif
00296 codeset = result;
00297 new_binding->codeset_cntr++;
00298 }
00299 *codesetp = codeset;
00300 new_binding->codeset = (char *) codeset;
00301 }
00302 else
00303 new_binding->codeset = NULL;
00304
00305
00306 if (_nl_domain_bindings == NULL
00307 || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
00308 {
00309 new_binding->next = _nl_domain_bindings;
00310 _nl_domain_bindings = new_binding;
00311 }
00312 else
00313 {
00314 binding = _nl_domain_bindings;
00315 while (binding->next != NULL
00316 && strcmp (domainname, binding->next->domainname) > 0)
00317 binding = binding->next;
00318
00319 new_binding->next = binding->next;
00320 binding->next = new_binding;
00321 }
00322
00323 modified = 1;
00324
00325
00326 if (0)
00327 {
00328 failed_codeset:
00329 if (new_binding->dirname != INTUSE(_nl_default_dirname))
00330 free (new_binding->dirname);
00331 failed_dirname:
00332 free (new_binding);
00333 failed:
00334 if (dirnamep)
00335 *dirnamep = NULL;
00336 if (codesetp)
00337 *codesetp = NULL;
00338 }
00339 }
00340
00341
00342 if (modified)
00343 ++_nl_msg_cat_cntr;
00344
00345 __libc_rwlock_unlock (_nl_state_lock);
00346 }
00347
00348
00349
00350 char *
00351 BINDTEXTDOMAIN (domainname, dirname)
00352 const char *domainname;
00353 const char *dirname;
00354 {
00355 set_binding_values (domainname, &dirname, NULL);
00356 return (char *) dirname;
00357 }
00358
00359
00360
00361 char *
00362 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
00363 const char *domainname;
00364 const char *codeset;
00365 {
00366 set_binding_values (domainname, NULL, &codeset);
00367 return (char *) codeset;
00368 }
00369
00370 #ifdef _LIBC
00371
00372 weak_alias (__bindtextdomain, bindtextdomain);
00373 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
00374 #endif