2005-03-22 Roland McGrath <roland@redhat.com>
[kopensolaris-gnu/glibc.git] / intl / dcigettext.c
index 81bfdce..75762ea 100644 (file)
@@ -1,5 +1,5 @@
 /* Implementation of the internal dcigettext function.
-   Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1995-2002,2003,2004,2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -103,10 +103,10 @@ extern int errno;
    names than the internal variables in GNU libc, otherwise programs
    using libintl.a cannot be linked statically.  */
 #if !defined _LIBC
-# define _nl_default_default_domain _nl_default_default_domain__
-# define _nl_current_default_domain _nl_current_default_domain__
-# define _nl_default_dirname _nl_default_dirname__
-# define _nl_domain_bindings _nl_domain_bindings__
+# define _nl_default_default_domain libintl_nl_default_default_domain
+# define _nl_current_default_domain libintl_nl_current_default_domain
+# define _nl_default_dirname libintl_nl_default_dirname
+# define _nl_domain_bindings libintl_nl_domain_bindings
 #endif
 
 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>.  */
@@ -236,13 +236,6 @@ transcmp (p1, p2)
 }
 #endif
 
-#ifndef INTVARDEF
-# define INTVARDEF
-#endif
-#ifndef INTUSE
-# define INTUSE(name) name
-#endif
-
 /* Name of the default domain used for gettext(3) prior any call to
    textdomain(3).  The default value for this is "messages".  */
 const char _nl_default_default_domain[] attribute_hidden = "messages";
@@ -252,8 +245,15 @@ const char *_nl_current_default_domain attribute_hidden
      = _nl_default_default_domain;
 
 /* Contains the default location of the message catalogs.  */
+
+#ifdef _LIBC
+extern const char _nl_default_dirname[];
+libc_hidden_proto (_nl_default_dirname)
+#endif
 const char _nl_default_dirname[] = LOCALEDIR;
-INTVARDEF (_nl_default_dirname)
+#ifdef _LIBC
+libc_hidden_data_def (_nl_default_dirname)
+#endif
 
 /* List with bindings of specific domains created by bindtextdomain()
    calls.  */
@@ -280,6 +280,7 @@ static const char *category_to_name PARAMS ((int category)) internal_function;
    some additional code emulating it.  */
 #ifdef HAVE_ALLOCA
 /* Nothing has to be done.  */
+# define freea(p) /* nothing */
 # define ADD_BLOCK(list, address) /* nothing */
 # define FREE_BLOCKS(list) /* nothing */
 #else
@@ -304,11 +305,13 @@ struct block_list
     while (list != NULL) {                                                   \
       struct block_list *old = list;                                         \
       list = list->next;                                                     \
+      free (old->address);                                                   \
       free (old);                                                            \
     }                                                                        \
   } while (0)
 # undef alloca
 # define alloca(size) (malloc (size))
+# define freea(p) free (p)
 #endif /* have alloca */
 
 
@@ -332,7 +335,7 @@ typedef unsigned char transmem_block_t;
 #ifdef _LIBC
 # define DCIGETTEXT __dcigettext
 #else
-# define DCIGETTEXT dcigettext__
+# define DCIGETTEXT libintl_dcigettext
 #endif
 
 /* Lock variable to protect the global data in the gettext implementation.  */
@@ -346,6 +349,18 @@ __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
 # define ENABLE_SECURE __libc_enable_secure
 # define DETERMINE_SECURE
 #else
+# ifndef HAVE_GETUID
+#  define getuid() 0
+# endif
+# ifndef HAVE_GETGID
+#  define getgid() 0
+# endif
+# ifndef HAVE_GETEUID
+#  define geteuid() getuid()
+# endif
+# ifndef HAVE_GETEGID
+#  define getegid() getgid()
+# endif
 static int enable_secure;
 # define ENABLE_SECURE (enable_secure == 1)
 # define DETERMINE_SECURE \
@@ -424,7 +439,16 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
   search->domainname = (char *) domainname;
   search->category = category;
 
+  /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
+     tsearch calls can be fatal.  */
+  __libc_rwlock_define_initialized (static, tree_lock);
+  __libc_rwlock_rdlock (tree_lock);
+
   foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+
+  __libc_rwlock_unlock (tree_lock);
+
+  freea (search);
   if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
     {
       /* Now deal with plural.  */
@@ -461,7 +485,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
     }
 
   if (binding == NULL)
-    dirname = (char *) INTUSE(_nl_default_dirname);
+    dirname = (char *) _nl_default_dirname;
   else if (binding->dirname[0] == '/')
     dirname = binding->dirname;
   else
@@ -597,7 +621,6 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
              /* Found the translation of MSGID1 in domain DOMAIN:
                 starting at RETVAL, RETLEN bytes.  */
              FREE_BLOCKS (block_list);
-             __set_errno (saved_errno);
 #if defined HAVE_TSEARCH || defined _LIBC
              if (foundp == NULL)
                {
@@ -618,9 +641,14 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
                      newp->translation = retval;
                      newp->translation_length = retlen;
 
+                     __libc_rwlock_wrlock (tree_lock);
+
                      /* Insert the entry in the search tree.  */
                      foundp = (struct known_translation_t **)
                        tsearch (newp, &root, transcmp);
+
+                     __libc_rwlock_unlock (tree_lock);
+
                      if (foundp == NULL
                          || __builtin_expect (*foundp != newp, 0))
                        /* The insert failed.  */
@@ -636,6 +664,8 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
                  (*foundp)->translation_length = retlen;
                }
 #endif
+             __set_errno (saved_errno);
+
              /* Now deal with plural.  */
              if (plural)
                retval = plural_lookup (domain, n, retval, retlen);
@@ -663,7 +693,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
   char *result;
   size_t resultlen;
 
-  if (domain_file->decided == 0)
+  if (domain_file->decided <= 0)
     _nl_load_domain (domain_file, domainbinding);
 
   if (domain_file->data == NULL)
@@ -678,7 +708,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
     {
       /* Use the hashing table.  */
       nls_uint32 len = strlen (msgid);
-      nls_uint32 hash_val = hash_string (msgid);
+      nls_uint32 hash_val = __hash_string (msgid);
       nls_uint32 idx = hash_val % domain->hash_size;
       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
 
@@ -852,7 +882,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
                  goto converted;
                }
 
-             inbuf = result;
+             inbuf = (const unsigned char *) result;
 # else
 #  if HAVE_ICONV
              const char *inptr = (const char *) inbuf;
@@ -920,7 +950,7 @@ _nl_find_msg (domain_file, domainbinding, msgid, lengthp)
              newmem->next = transmem_list;
              transmem_list = newmem;
 
-             freemem = newmem->data;
+             freemem = (unsigned char *) newmem->data;
              freemem_size -= offsetof (struct transmem_list, data);
 # else
              transmem_list = newmem;
@@ -1123,8 +1153,7 @@ mempcpy (dest, src, n)
 #ifdef _LIBC
 /* If we want to free all resources we have to do some work at
    program's end.  */
-static void __attribute__ ((unused))
-free_mem (void)
+libc_freeres_fn (free_mem)
 {
   void *old;
 
@@ -1132,7 +1161,7 @@ free_mem (void)
     {
       struct binding *oldp = _nl_domain_bindings;
       _nl_domain_bindings = _nl_domain_bindings->next;
-      if (oldp->dirname != INTUSE(_nl_default_dirname))
+      if (oldp->dirname != _nl_default_dirname)
        /* Yes, this is a pointer comparison.  */
        free (oldp->dirname);
       free (oldp->codeset);
@@ -1154,6 +1183,4 @@ free_mem (void)
       free (old);
     }
 }
-
-text_set_element (__libc_subfreeres, free_mem);
 #endif