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