bindtextdom.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:10k
源码类别:

多媒体

开发平台:

MultiPlatform

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