home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / gettext / intl / bindtextdom.c next >
Encoding:
C/C++ Source or Header  |  2010-09-19  |  8.7 KB  |  341 lines

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