"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.2/intl/bindtextdom.c" (23 Aug 2021, 9850 Bytes) of package /linux/misc/tin-2.6.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* Implementation of the bindtextdomain(3) function
    2    Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
    3 
    4    This program is free software; you can redistribute it and/or modify it
    5    under the terms of the GNU Library General Public License as published
    6    by the Free Software Foundation; either version 2, or (at your option)
    7    any later version.
    8 
    9    This program is distributed in the hope that it will be useful,
   10    but WITHOUT ANY WARRANTY; without even the implied warranty of
   11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12    Library General Public License for more details.
   13 
   14    You should have received a copy of the GNU Library General Public
   15    License along with this program; if not, write to the Free Software
   16    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
   17    USA.  */
   18 
   19 #ifdef HAVE_CONFIG_H
   20 # include <autoconf.h>
   21 #endif
   22 
   23 #include <stddef.h>
   24 #include <stdlib.h>
   25 #include <string.h>
   26 
   27 #ifdef _LIBC
   28 # include <libintl.h>
   29 #else
   30 # include "libgnuintl.h"
   31 #endif
   32 #include "gettextP.h"
   33 
   34 #ifdef _LIBC
   35 /* We have to handle multi-threaded applications.  */
   36 # include <bits/libc-lock.h>
   37 #else
   38 /* Provide dummy implementation if this is outside glibc.  */
   39 # define __libc_rwlock_define(CLASS, NAME)
   40 # define __libc_rwlock_wrlock(NAME)
   41 # define __libc_rwlock_unlock(NAME)
   42 #endif
   43 
   44 /* The internal variables in the standalone libintl.a must have different
   45    names than the internal variables in GNU libc, otherwise programs
   46    using libintl.a cannot be linked statically.  */
   47 #if !defined _LIBC
   48 # define _nl_default_dirname _nl_default_dirname__
   49 # define _nl_domain_bindings _nl_domain_bindings__
   50 #endif
   51 
   52 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
   53 #ifndef offsetof
   54 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
   55 #endif
   56 
   57 /* @@ end of prolog @@ */
   58 
   59 /* Contains the default location of the message catalogs.  */
   60 extern const char _nl_default_dirname[];
   61 
   62 /* List with bindings of specific domains.  */
   63 extern struct binding *_nl_domain_bindings;
   64 
   65 /* Lock variable to protect the global data in the gettext implementation.  */
   66 __libc_rwlock_define (extern, _nl_state_lock)
   67 
   68 
   69 /* Names for the libintl functions are a problem.  They must not clash
   70    with existing names and they should follow ANSI C.  But this source
   71    code is also used in GNU C Library where the names have a __
   72    prefix.  So we have to make a difference here.  */
   73 #ifdef _LIBC
   74 # define BINDTEXTDOMAIN __bindtextdomain
   75 # define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
   76 # ifndef strdup
   77 #  define strdup(str) __strdup (str)
   78 # endif
   79 #else
   80 # define BINDTEXTDOMAIN bindtextdomain__
   81 # define BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset__
   82 #endif
   83 
   84 /* Prototypes for local functions.  */
   85 static void set_binding_values PARAMS ((const char *domainname,
   86                     const char **dirnamep,
   87                     const char **codesetp));
   88      
   89 /* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
   90    to be used for the DOMAINNAME message catalog.
   91    If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
   92    modified, only the current value is returned.
   93    If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
   94    modified nor returned.  */
   95 static void
   96 set_binding_values (domainname, dirnamep, codesetp)
   97      const char *domainname;
   98      const char **dirnamep;
   99      const char **codesetp;
  100 {
  101   struct binding *binding;
  102   int modified;
  103 
  104   /* Some sanity checks.  */
  105   if (domainname == NULL || domainname[0] == '\0')
  106     {
  107       if (dirnamep)
  108     *dirnamep = NULL;
  109       if (codesetp)
  110     *codesetp = NULL;
  111       return;
  112     }
  113 
  114   __libc_rwlock_wrlock (_nl_state_lock);
  115 
  116   modified = 0;
  117 
  118   for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
  119     {
  120       int compare = strcmp (domainname, binding->domainname);
  121       if (compare == 0)
  122     /* We found it!  */
  123     break;
  124       if (compare < 0)
  125     {
  126       /* It is not in the list.  */
  127       binding = NULL;
  128       break;
  129     }
  130     }
  131 
  132   if (binding != NULL)
  133     {
  134       if (dirnamep)
  135     {
  136       const char *dirname = *dirnamep;
  137 
  138       if (dirname == NULL)
  139         /* The current binding has be to returned.  */
  140         *dirnamep = binding->dirname;
  141       else
  142         {
  143           /* The domain is already bound.  If the new value and the old
  144          one are equal we simply do nothing.  Otherwise replace the
  145          old binding.  */
  146           char *result = binding->dirname;
  147           if (strcmp (dirname, result) != 0)
  148         {
  149           if (strcmp (dirname, _nl_default_dirname) == 0)
  150             result = (char *) _nl_default_dirname;
  151           else
  152             {
  153 #if defined _LIBC || defined HAVE_STRDUP
  154               result = strdup (dirname);
  155 #else
  156               size_t len = strlen (dirname) + 1;
  157               result = (char *) malloc (len);
  158               if (__builtin_expect (result != NULL, 1))
  159             memcpy (result, dirname, len);
  160 #endif
  161             }
  162 
  163           if (__builtin_expect (result != NULL, 1))
  164             {
  165               if (binding->dirname != _nl_default_dirname)
  166             free (binding->dirname);
  167 
  168               binding->dirname = result;
  169               modified = 1;
  170             }
  171         }
  172           *dirnamep = result;
  173         }
  174     }
  175 
  176       if (codesetp)
  177     {
  178       const char *codeset = *codesetp;
  179 
  180       if (codeset == NULL)
  181         /* The current binding has be to returned.  */
  182         *codesetp = binding->codeset;
  183       else
  184         {
  185           /* The domain is already bound.  If the new value and the old
  186          one are equal we simply do nothing.  Otherwise replace the
  187          old binding.  */
  188           char *result = binding->codeset;
  189           if (result == NULL || strcmp (codeset, result) != 0)
  190         {
  191 #if defined _LIBC || defined HAVE_STRDUP
  192           result = strdup (codeset);
  193 #else
  194           size_t len = strlen (codeset) + 1;
  195           result = (char *) malloc (len);
  196           if (__builtin_expect (result != NULL, 1))
  197             memcpy (result, codeset, len);
  198 #endif
  199 
  200           if (__builtin_expect (result != NULL, 1))
  201             {
  202               if (binding->codeset != NULL)
  203             free (binding->codeset);
  204 
  205               binding->codeset = result;
  206               binding->codeset_cntr++;
  207               modified = 1;
  208             }
  209         }
  210           *codesetp = result;
  211         }
  212     }
  213     }
  214   else if ((dirnamep == NULL || *dirnamep == NULL)
  215        && (codesetp == NULL || *codesetp == NULL))
  216     {
  217       /* Simply return the default values.  */
  218       if (dirnamep)
  219     *dirnamep = _nl_default_dirname;
  220       if (codesetp)
  221     *codesetp = NULL;
  222     }
  223   else
  224     {
  225       /* We have to create a new binding.  */
  226       size_t len = strlen (domainname) + 1;
  227       struct binding *new_binding =
  228     (struct binding *) malloc (offsetof (struct binding, domainname) + len);
  229 
  230       if (__builtin_expect (new_binding == NULL, 0))
  231     goto failed;
  232 
  233       memcpy (new_binding->domainname, domainname, len);
  234 
  235       if (dirnamep)
  236     {
  237       const char *dirname = *dirnamep;
  238 
  239       if (dirname == NULL)
  240         /* The default value.  */
  241         dirname = _nl_default_dirname;
  242       else
  243         {
  244           if (strcmp (dirname, _nl_default_dirname) == 0)
  245         dirname = _nl_default_dirname;
  246           else
  247         {
  248           char *result;
  249 #if defined _LIBC || defined HAVE_STRDUP
  250           result = strdup (dirname);
  251           if (__builtin_expect (result == NULL, 0))
  252             goto failed_dirname;
  253 #else
  254           size_t len = strlen (dirname) + 1;
  255           result = (char *) malloc (len);
  256           if (__builtin_expect (result == NULL, 0))
  257             goto failed_dirname;
  258           memcpy (result, dirname, len);
  259 #endif
  260           dirname = result;
  261         }
  262         }
  263       *dirnamep = dirname;
  264       new_binding->dirname = (char *) dirname;
  265     }
  266       else
  267     /* The default value.  */
  268     new_binding->dirname = (char *) _nl_default_dirname;
  269 
  270       new_binding->codeset_cntr = 0;
  271 
  272       if (codesetp)
  273     {
  274       const char *codeset = *codesetp;
  275 
  276       if (codeset != NULL)
  277         {
  278           char *result;
  279 
  280 #if defined _LIBC || defined HAVE_STRDUP
  281           result = strdup (codeset);
  282           if (__builtin_expect (result == NULL, 0))
  283         goto failed_codeset;
  284 #else
  285           size_t len = strlen (codeset) + 1;
  286           result = (char *) malloc (len);
  287           if (__builtin_expect (result == NULL, 0))
  288         goto failed_codeset;
  289           memcpy (result, codeset, len);
  290 #endif
  291           codeset = result;
  292           new_binding->codeset_cntr++;
  293         }
  294       *codesetp = codeset;
  295       new_binding->codeset = (char *) codeset;
  296     }
  297       else
  298     new_binding->codeset = NULL;
  299 
  300       /* Now enqueue it.  */
  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       /* Here we deal with memory allocation failures.  */
  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   /* If we modified any binding, we flush the caches.  */
  337   if (modified)
  338     ++_nl_msg_cat_cntr;
  339 
  340   __libc_rwlock_unlock (_nl_state_lock);
  341 }
  342 
  343 /* Specify that the DOMAINNAME message catalog will be found
  344    in DIRNAME rather than in the system locale data base.  */
  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 /* Specify the character encoding in which the messages from the
  355    DOMAINNAME message catalog will be returned.  */
  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 /* Aliases for function names in GNU C Library.  */
  367 weak_alias (__bindtextdomain, bindtextdomain);
  368 weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
  369 #endif