Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

bindtextdom.c

00001 /* Implementation of the bindtextdomain(3) function
00002    Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
00003 
00004    This program is free software; you can redistribute it and/or modify it
00005    under the terms of the GNU Library General Public License as published
00006    by the Free Software Foundation; either version 2, or (at your option)
00007    any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public
00015    License along with this program; if not, write to the Free Software
00016    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00017    USA.  */
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 /* We have to handle multi-threaded applications.  */
00036 # include <bits/libc-lock.h>
00037 #else
00038 /* Provide dummy implementation if this is outside glibc.  */
00039 # define __libc_rwlock_define(CLASS, NAME)
00040 # define __libc_rwlock_wrlock(NAME)
00041 # define __libc_rwlock_unlock(NAME)
00042 #endif
00043 
00044 /* The internal variables in the standalone libintl.a must have different
00045    names than the internal variables in GNU libc, otherwise programs
00046    using libintl.a cannot be linked statically.  */
00047 #if !defined _LIBC
00048 # define _nl_default_dirname _nl_default_dirname__
00049 # define _nl_domain_bindings _nl_domain_bindings__
00050 #endif
00051 
00052 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
00053 #ifndef offsetof
00054 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
00055 #endif
00056 
00057 /* @@ end of prolog @@ */
00058 
00059 /* Contains the default location of the message catalogs.  */
00060 extern const char _nl_default_dirname[];
00061 
00062 /* List with bindings of specific domains.  */
00063 extern struct binding *_nl_domain_bindings;
00064 
00065 /* Lock variable to protect the global data in the gettext implementation.  */
00066 __libc_rwlock_define (extern, _nl_state_lock)
00067 
00068 
00069 /* Names for the libintl functions are a problem.  They must not clash
00070    with existing names and they should follow ANSI C.  But this source
00071    code is also used in GNU C Library where the names have a __
00072    prefix.  So we have to make a difference here.  */
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 bindtextdomain__
00081 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
00082 #endif
00083 
00084 /* Prototypes for local functions.  */
00085 static void set_binding_values PARAMS ((const char *domainname,
00086                                         const char **dirnamep,
00087                                         const char **codesetp));
00088 
00089 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
00090    to be used for the DOMAINNAME message catalog.
00091    If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
00092    modified, only the current value is returned.
00093    If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
00094    modified nor returned.  */
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   /* Some sanity checks.  */
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         /* We found it!  */
00123         break;
00124       if (compare < 0)
00125         {
00126           /* It is not in the list.  */
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             /* The current binding has be to returned.  */
00140             *dirnamep = binding->dirname;
00141           else
00142             {
00143               /* The domain is already bound.  If the new value and the old
00144                  one are equal we simply do nothing.  Otherwise replace the
00145                  old binding.  */
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             /* The current binding has be to returned.  */
00182             *codesetp = binding->codeset;
00183           else
00184             {
00185               /* The domain is already bound.  If the new value and the old
00186                  one are equal we simply do nothing.  Otherwise replace the
00187                  old binding.  */
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       /* Simply return the default values.  */
00218       if (dirnamep)
00219         *dirnamep = _nl_default_dirname;
00220       if (codesetp)
00221         *codesetp = NULL;
00222     }
00223   else
00224     {
00225       /* We have to create a new binding.  */
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             /* The default value.  */
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         /* The default value.  */
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       /* Now enqueue it.  */
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       /* Here we deal with memory allocation failures.  */
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   /* If we modified any binding, we flush the caches.  */
00337   if (modified)
00338     ++_nl_msg_cat_cntr;
00339 
00340   __libc_rwlock_unlock (_nl_state_lock);
00341 }
00342 
00343 /* Specify that the DOMAINNAME message catalog will be found
00344    in DIRNAME rather than in the system locale data base.  */
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 /* Specify the character encoding in which the messages from the
00355    DOMAINNAME message catalog will be returned.  */
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 /* Aliases for function names in GNU C Library.  */
00367 weak_alias (__bindtextdomain, bindtextdomain);
00368 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
00369 #endif

Generated on Sun Feb 16 23:39:49 2003 for FreeLCD by doxygen1.2.18