Back to index

glibc  2.9
bindtextdom.c
Go to the documentation of this file.
00001 /* Implementation of the bindtextdomain(3) function
00002    Copyright (C) 1995-1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #ifdef HAVE_CONFIG_H
00021 # include <config.h>
00022 #endif
00023 
00024 #include <stddef.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 
00028 #ifdef _LIBC
00029 # include <libintl.h>
00030 #else
00031 # include "libgnuintl.h"
00032 #endif
00033 #include "gettextP.h"
00034 
00035 #ifdef _LIBC
00036 /* We have to handle multi-threaded applications.  */
00037 # include <bits/libc-lock.h>
00038 #else
00039 /* Provide dummy implementation if this is outside glibc.  */
00040 # define __libc_rwlock_define(CLASS, NAME)
00041 # define __libc_rwlock_wrlock(NAME)
00042 # define __libc_rwlock_unlock(NAME)
00043 #endif
00044 
00045 /* The internal variables in the standalone libintl.a must have different
00046    names than the internal variables in GNU libc, otherwise programs
00047    using libintl.a cannot be linked statically.  */
00048 #if !defined _LIBC
00049 # define _nl_default_dirname libintl_nl_default_dirname
00050 # define _nl_domain_bindings libintl_nl_domain_bindings
00051 #endif
00052 
00053 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
00054 #ifndef offsetof
00055 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
00056 #endif
00057 
00058 /* @@ end of prolog @@ */
00059 
00060 /* Contains the default location of the message catalogs.  */
00061 extern const char _nl_default_dirname[];
00062 #ifdef _LIBC
00063 libc_hidden_proto (_nl_default_dirname)
00064 #endif
00065 
00066 /* List with bindings of specific domains.  */
00067 extern struct binding *_nl_domain_bindings;
00068 
00069 /* Lock variable to protect the global data in the gettext implementation.  */
00070 __libc_rwlock_define (extern, _nl_state_lock attribute_hidden)
00071 
00072 
00073 /* Names for the libintl functions are a problem.  They must not clash
00074    with existing names and they should follow ANSI C.  But this source
00075    code is also used in GNU C Library where the names have a __
00076    prefix.  So we have to make a difference here.  */
00077 #ifdef _LIBC
00078 # define BINDTEXTDOMAIN __bindtextdomain
00079 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
00080 # ifndef strdup
00081 #  define strdup(str) __strdup (str)
00082 # endif
00083 #else
00084 # define BINDTEXTDOMAIN libintl_bindtextdomain
00085 # define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
00086 #endif
00087 
00088 /* Prototypes for local functions.  */
00089 static void set_binding_values PARAMS ((const char *domainname,
00090                                    const char **dirnamep,
00091                                    const char **codesetp));
00092 
00093 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
00094    to be used for the DOMAINNAME message catalog.
00095    If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
00096    modified, only the current value is returned.
00097    If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
00098    modified nor returned.  */
00099 static void
00100 set_binding_values (domainname, dirnamep, codesetp)
00101      const char *domainname;
00102      const char **dirnamep;
00103      const char **codesetp;
00104 {
00105   struct binding *binding;
00106   int modified;
00107 
00108   /* Some sanity checks.  */
00109   if (domainname == NULL || domainname[0] == '\0')
00110     {
00111       if (dirnamep)
00112        *dirnamep = NULL;
00113       if (codesetp)
00114        *codesetp = NULL;
00115       return;
00116     }
00117 
00118   __libc_rwlock_wrlock (_nl_state_lock);
00119 
00120   modified = 0;
00121 
00122   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
00123     {
00124       int compare = strcmp (domainname, binding->domainname);
00125       if (compare == 0)
00126        /* We found it!  */
00127        break;
00128       if (compare < 0)
00129        {
00130          /* It is not in the list.  */
00131          binding = NULL;
00132          break;
00133        }
00134     }
00135 
00136   if (binding != NULL)
00137     {
00138       if (dirnamep)
00139        {
00140          const char *dirname = *dirnamep;
00141 
00142          if (dirname == NULL)
00143            /* The current binding has be to returned.  */
00144            *dirnamep = binding->dirname;
00145          else
00146            {
00147              /* The domain is already bound.  If the new value and the old
00148                one are equal we simply do nothing.  Otherwise replace the
00149                old binding.  */
00150              char *result = binding->dirname;
00151              if (strcmp (dirname, result) != 0)
00152               {
00153                 if (strcmp (dirname, _nl_default_dirname) == 0)
00154                   result = (char *) _nl_default_dirname;
00155                 else
00156                   {
00157 #if defined _LIBC || defined HAVE_STRDUP
00158                     result = strdup (dirname);
00159 #else
00160                     size_t len = strlen (dirname) + 1;
00161                     result = (char *) malloc (len);
00162                     if (__builtin_expect (result != NULL, 1))
00163                      memcpy (result, dirname, len);
00164 #endif
00165                   }
00166 
00167                 if (__builtin_expect (result != NULL, 1))
00168                   {
00169                     if (binding->dirname != _nl_default_dirname)
00170                      free (binding->dirname);
00171 
00172                     binding->dirname = result;
00173                     modified = 1;
00174                   }
00175               }
00176              *dirnamep = result;
00177            }
00178        }
00179 
00180       if (codesetp)
00181        {
00182          const char *codeset = *codesetp;
00183 
00184          if (codeset == NULL)
00185            /* The current binding has be to returned.  */
00186            *codesetp = binding->codeset;
00187          else
00188            {
00189              /* The domain is already bound.  If the new value and the old
00190                one are equal we simply do nothing.  Otherwise replace the
00191                old binding.  */
00192              char *result = binding->codeset;
00193              if (result == NULL || strcmp (codeset, result) != 0)
00194               {
00195 #if defined _LIBC || defined HAVE_STRDUP
00196                 result = strdup (codeset);
00197 #else
00198                 size_t len = strlen (codeset) + 1;
00199                 result = (char *) malloc (len);
00200                 if (__builtin_expect (result != NULL, 1))
00201                   memcpy (result, codeset, len);
00202 #endif
00203 
00204                 if (__builtin_expect (result != NULL, 1))
00205                   {
00206                     free (binding->codeset);
00207 
00208                     binding->codeset = result;
00209                     modified = 1;
00210                   }
00211               }
00212              *codesetp = result;
00213            }
00214        }
00215     }
00216   else if ((dirnamep == NULL || *dirnamep == NULL)
00217           && (codesetp == NULL || *codesetp == NULL))
00218     {
00219       /* Simply return the default values.  */
00220       if (dirnamep)
00221        *dirnamep = _nl_default_dirname;
00222       if (codesetp)
00223        *codesetp = NULL;
00224     }
00225   else
00226     {
00227       /* We have to create a new binding.  */
00228       size_t len = strlen (domainname) + 1;
00229       struct binding *new_binding =
00230        (struct binding *) malloc (offsetof (struct binding, domainname) + len);
00231 
00232       if (__builtin_expect (new_binding == NULL, 0))
00233        goto failed;
00234 
00235       memcpy (new_binding->domainname, domainname, len);
00236 
00237       if (dirnamep)
00238        {
00239          const char *dirname = *dirnamep;
00240 
00241          if (dirname == NULL)
00242            /* The default value.  */
00243            dirname = _nl_default_dirname;
00244          else
00245            {
00246              if (strcmp (dirname, _nl_default_dirname) == 0)
00247               dirname = _nl_default_dirname;
00248              else
00249               {
00250                 char *result;
00251 #if defined _LIBC || defined HAVE_STRDUP
00252                 result = strdup (dirname);
00253                 if (__builtin_expect (result == NULL, 0))
00254                   goto failed_dirname;
00255 #else
00256                 size_t len = strlen (dirname) + 1;
00257                 result = (char *) malloc (len);
00258                 if (__builtin_expect (result == NULL, 0))
00259                   goto failed_dirname;
00260                 memcpy (result, dirname, len);
00261 #endif
00262                 dirname = result;
00263               }
00264            }
00265          *dirnamep = dirname;
00266          new_binding->dirname = (char *) dirname;
00267        }
00268       else
00269        /* The default value.  */
00270        new_binding->dirname = (char *) _nl_default_dirname;
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            }
00293          *codesetp = codeset;
00294          new_binding->codeset = (char *) codeset;
00295        }
00296       else
00297        new_binding->codeset = NULL;
00298 
00299       /* Now enqueue it.  */
00300       if (_nl_domain_bindings == NULL
00301          || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
00302        {
00303          new_binding->next = _nl_domain_bindings;
00304          _nl_domain_bindings = new_binding;
00305        }
00306       else
00307        {
00308          binding = _nl_domain_bindings;
00309          while (binding->next != NULL
00310                && strcmp (domainname, binding->next->domainname) > 0)
00311            binding = binding->next;
00312 
00313          new_binding->next = binding->next;
00314          binding->next = new_binding;
00315        }
00316 
00317       modified = 1;
00318 
00319       /* Here we deal with memory allocation failures.  */
00320       if (0)
00321        {
00322        failed_codeset:
00323          if (new_binding->dirname != _nl_default_dirname)
00324            free (new_binding->dirname);
00325        failed_dirname:
00326          free (new_binding);
00327        failed:
00328          if (dirnamep)
00329            *dirnamep = NULL;
00330          if (codesetp)
00331            *codesetp = NULL;
00332        }
00333     }
00334 
00335   /* If we modified any binding, we flush the caches.  */
00336   if (modified)
00337     ++_nl_msg_cat_cntr;
00338 
00339   __libc_rwlock_unlock (_nl_state_lock);
00340 }
00341 
00342 /* Specify that the DOMAINNAME message catalog will be found
00343    in DIRNAME rather than in the system locale data base.  */
00344 char *
00345 BINDTEXTDOMAIN (domainname, dirname)
00346      const char *domainname;
00347      const char *dirname;
00348 {
00349   set_binding_values (domainname, &dirname, NULL);
00350   return (char *) dirname;
00351 }
00352 
00353 /* Specify the character encoding in which the messages from the
00354    DOMAINNAME message catalog will be returned.  */
00355 char *
00356 BIND_TEXTDOMAIN_CODESET (domainname, codeset)
00357      const char *domainname;
00358      const char *codeset;
00359 {
00360   set_binding_values (domainname, NULL, &codeset);
00361   return (char *) codeset;
00362 }
00363 
00364 #ifdef _LIBC
00365 /* Aliases for function names in GNU C Library.  */
00366 weak_alias (__bindtextdomain, bindtextdomain);
00367 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
00368 #endif