Back to index

courier  0.68.2
Classes | Defines | Functions | Variables
gettextP.h File Reference
#include <stddef.h>
#include "lock.h"
#include "libgnuintl.h"
#include "loadinfo.h"
#include "gmo.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  converted_domain
struct  loaded_domain
struct  binding

Defines

#define _INTL_REDIRECT_MACROS
#define attribute_hidden    _nl_default_default_domain
#define __builtin_expect(expr, val)   (expr)
#define W(flag, data)   ((flag) ? SWAP (data) : (data))
#define ZERO   1
#define gl_locale_name_canonicalize   _nl_locale_name_canonicalize
#define gl_locale_name_from_win32_LANGID   _nl_locale_name_from_win32_LANGID
#define gl_locale_name_from_win32_LCID   _nl_locale_name_from_win32_LCID
#define gl_locale_name_thread_unsafe   _nl_locale_name_thread_unsafe
#define gl_locale_name_thread   _nl_locale_name_thread
#define gl_locale_name_posix   _nl_locale_name_posix
#define gl_locale_name_environ   _nl_locale_name_environ
#define gl_locale_name_default   _nl_locale_name_default
#define gl_locale_name   _nl_locale_name
#define _nl_default_dirname   libintl_nl_default_dirname
#define _nl_domain_bindings   libintl_nl_domain_bindings
#define _nl_default_default_domain   libintl_nl_default_default_domain
#define _nl_current_default_domain   libintl_nl_current_default_domain

Functions

char * libintl_dcigettext (const char *__domainname, const char *__msgid1, const char *__msgid2, int __plural, unsigned long int __n, int __category)
const char * _nl_language_preferences_default (void)
void _nl_locale_name_canonicalize (char *name)
const char * _nl_locale_name_thread_unsafe (int category, const char *categoryname)
const char * _nl_locale_name_posix (int category, const char *categoryname)
const char * _nl_locale_name_environ (int category, const char *categoryname)
const char * _nl_locale_name_default (void)
struct loaded_l10nfile_nl_find_domain (const char *__dirname, char *__locale, const char *__domainname, struct binding *__domainbinding) internal_function
void _nl_load_domain (struct loaded_l10nfile *__domain, struct binding *__domainbinding) internal_function
char * _nl_find_msg (struct loaded_l10nfile *domain_file, struct binding *domainbinding, const char *msgid, int convert, size_t *lengthp) internal_function

Variables

static nls_uint32 nls_uint32 i
LIBINTL_DLL_EXPORTED int _nl_msg_cat_cntr
const char _nl_default_dirname []
struct binding_nl_domain_bindings
const char
_nl_default_default_domain[] 
attribute_hidden

Class Documentation

struct converted_domain

Definition at line 141 of file gettextP.h.

Class Members
char ** conv_tab
const char * encoding
struct binding

Definition at line 212 of file gettextP.h.

Collaboration diagram for binding:
Class Members
char * codeset
char * dirname
char domainname
struct binding * next

Define Documentation

#define __builtin_expect (   expr,
  val 
)    (expr)

Definition at line 104 of file gettextP.h.

Definition at line 71 of file gettextP.h.

#define _nl_current_default_domain   libintl_nl_current_default_domain

Definition at line 300 of file gettextP.h.

#define _nl_default_default_domain   libintl_nl_default_default_domain

Definition at line 299 of file gettextP.h.

Definition at line 282 of file gettextP.h.

#define _nl_domain_bindings   libintl_nl_domain_bindings

Definition at line 283 of file gettextP.h.

Definition at line 98 of file gettextP.h.

#define gl_locale_name   _nl_locale_name

Definition at line 252 of file gettextP.h.

Definition at line 232 of file gettextP.h.

Definition at line 250 of file gettextP.h.

Definition at line 247 of file gettextP.h.

#define gl_locale_name_from_win32_LANGID   _nl_locale_name_from_win32_LANGID

Definition at line 234 of file gettextP.h.

#define gl_locale_name_from_win32_LCID   _nl_locale_name_from_win32_LCID

Definition at line 236 of file gettextP.h.

Definition at line 244 of file gettextP.h.

#define gl_locale_name_thread   _nl_locale_name_thread

Definition at line 241 of file gettextP.h.

Definition at line 238 of file gettextP.h.

#define W (   flag,
  data 
)    ((flag) ? SWAP (data) : (data))

Definition at line 108 of file gettextP.h.

#define ZERO   1

Definition at line 207 of file gettextP.h.


Function Documentation

struct loaded_l10nfile* _nl_find_domain ( const char *  __dirname,
char *  __locale,
const char *  __domainname,
struct binding __domainbinding 
) [read]

Definition at line 61 of file finddomain.c.

{
  struct loaded_l10nfile *retval;
  const char *language;
  const char *modifier;
  const char *territory;
  const char *codeset;
  const char *normalized_codeset;
  const char *alias_value;
  int mask;

  /* LOCALE can consist of up to four recognized parts for the XPG syntax:

              language[_territory][.codeset][@modifier]

     Beside the first part all of them are allowed to be missing.  If
     the full specified locale is not found, the less specific one are
     looked for.  The various parts will be stripped off according to
     the following order:
              (1) codeset
              (2) normalized codeset
              (3) territory
              (4) modifier
   */

  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
  gl_rwlock_define_initialized (static, lock);
  gl_rwlock_rdlock (lock);

  /* If we have already tested for this locale entry there has to
     be one data set in the list of loaded domains.  */
  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
                            strlen (dirname) + 1, 0, locale, NULL, NULL,
                            NULL, NULL, domainname, 0);

  gl_rwlock_unlock (lock);

  if (retval != NULL)
    {
      /* We know something about this locale.  */
      int cnt;

      if (retval->decided <= 0)
       _nl_load_domain (retval, domainbinding);

      if (retval->data != NULL)
       return retval;

      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
       {
         if (retval->successor[cnt]->decided <= 0)
           _nl_load_domain (retval->successor[cnt], domainbinding);

         if (retval->successor[cnt]->data != NULL)
           break;
       }

      return retval;
      /* NOTREACHED */
    }

  /* See whether the locale value is an alias.  If yes its value
     *overwrites* the alias name.  No test for the original value is
     done.  */
  alias_value = _nl_expand_alias (locale);
  if (alias_value != NULL)
    {
#if defined _LIBC || defined HAVE_STRDUP
      locale = strdup (alias_value);
      if (locale == NULL)
       return NULL;
#else
      size_t len = strlen (alias_value) + 1;
      locale = (char *) malloc (len);
      if (locale == NULL)
       return NULL;

      memcpy (locale, alias_value, len);
#endif
    }

  /* Now we determine the single parts of the locale name.  First
     look for the language.  Termination symbols are `_', '.', and `@'.  */
  mask = _nl_explode_name (locale, &language, &modifier, &territory,
                        &codeset, &normalized_codeset);
  if (mask == -1)
    /* This means we are out of core.  */
    return NULL;

  /* We need to protect modifying the _NL_LOADED_DOMAINS data.  */
  gl_rwlock_wrlock (lock);

  /* Create all possible locale entries which might be interested in
     generalization.  */
  retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
                            strlen (dirname) + 1, mask, language, territory,
                            codeset, normalized_codeset, modifier,
                            domainname, 1);

  gl_rwlock_unlock (lock);

  if (retval == NULL)
    /* This means we are out of core.  */
    goto out;

  if (retval->decided <= 0)
    _nl_load_domain (retval, domainbinding);
  if (retval->data == NULL)
    {
      int cnt;
      for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
       {
         if (retval->successor[cnt]->decided <= 0)
           _nl_load_domain (retval->successor[cnt], domainbinding);
         if (retval->successor[cnt]->data != NULL)
           break;
       }
    }

  /* The room for an alias was dynamically allocated.  Free it now.  */
  if (alias_value != NULL)
    free (locale);

out:
  /* The space for normalized_codeset is dynamically allocated.  Free it.  */
  if (mask & XPG_NORM_CODESET)
    free ((void *) normalized_codeset);

  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* _nl_find_msg ( struct loaded_l10nfile domain_file,
struct binding domainbinding,
const char *  msgid,
int  convert,
size_t *  lengthp 
)

Definition at line 888 of file dcigettext.c.

{
  struct loaded_domain *domain;
  nls_uint32 nstrings;
  size_t act;
  char *result;
  size_t resultlen;

  if (domain_file->decided <= 0)
    _nl_load_domain (domain_file, domainbinding);

  if (domain_file->data == NULL)
    return NULL;

  domain = (struct loaded_domain *) domain_file->data;

  nstrings = domain->nstrings;

  /* Locate the MSGID and its translation.  */
  if (domain->hash_tab != NULL)
    {
      /* Use the hashing table.  */
      nls_uint32 len = strlen (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));

      while (1)
       {
         nls_uint32 nstr =
           W (domain->must_swap_hash_tab, domain->hash_tab[idx]);

         if (nstr == 0)
           /* Hash table entry is empty.  */
           return NULL;

         nstr--;

         /* Compare msgid with the original string at index nstr.
            We compare the lengths with >=, not ==, because plural entries
            are represented by strings with an embedded NUL.  */
         if (nstr < nstrings
             ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
              && (strcmp (msgid,
                         domain->data + W (domain->must_swap,
                                         domain->orig_tab[nstr].offset))
                  == 0)
             : domain->orig_sysdep_tab[nstr - nstrings].length > len
              && (strcmp (msgid,
                         domain->orig_sysdep_tab[nstr - nstrings].pointer)
                  == 0))
           {
             act = nstr;
             goto found;
           }

         if (idx >= domain->hash_size - incr)
           idx -= domain->hash_size - incr;
         else
           idx += incr;
       }
      /* NOTREACHED */
    }
  else
    {
      /* Try the default method:  binary search in the sorted array of
        messages.  */
      size_t top, bottom;

      bottom = 0;
      top = nstrings;
      while (bottom < top)
       {
         int cmp_val;

         act = (bottom + top) / 2;
         cmp_val = strcmp (msgid, (domain->data
                                + W (domain->must_swap,
                                    domain->orig_tab[act].offset)));
         if (cmp_val < 0)
           top = act;
         else if (cmp_val > 0)
           bottom = act + 1;
         else
           goto found;
       }
      /* No translation was found.  */
      return NULL;
    }

 found:
  /* The translation was found at index ACT.  If we have to convert the
     string to use a different character set, this is the time.  */
  if (act < nstrings)
    {
      result = (char *)
       (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
      resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
    }
  else
    {
      result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
      resultlen = domain->trans_sysdep_tab[act - nstrings].length;
    }

#if defined _LIBC || HAVE_ICONV
# ifdef IN_LIBGLOCALE
  if (encoding != NULL)
# else
  if (convert)
# endif
    {
      /* We are supposed to do a conversion.  */
# ifndef IN_LIBGLOCALE
      const char *encoding = get_output_charset (domainbinding);
# endif
      size_t nconversions;
      struct converted_domain *convd;
      size_t i;

      /* Protect against reallocation of the table.  */
      gl_rwlock_rdlock (domain->conversions_lock);

      /* Search whether a table with converted translations for this
        encoding has already been allocated.  */
      nconversions = domain->nconversions;
      convd = NULL;

      for (i = nconversions; i > 0; )
       {
         i--;
         if (strcmp (domain->conversions[i].encoding, encoding) == 0)
           {
             convd = &domain->conversions[i];
             break;
           }
       }

      gl_rwlock_unlock (domain->conversions_lock);

      if (convd == NULL)
       {
         /* We have to allocate a new conversions table.  */
         gl_rwlock_wrlock (domain->conversions_lock);
         nconversions = domain->nconversions;

         /* Maybe in the meantime somebody added the translation.
            Recheck.  */
         for (i = nconversions; i > 0; )
           {
             i--;
             if (strcmp (domain->conversions[i].encoding, encoding) == 0)
              {
                convd = &domain->conversions[i];
                goto found_convd;
              }
           }

         {
           /* Allocate a table for the converted translations for this
              encoding.  */
           struct converted_domain *new_conversions =
             (struct converted_domain *)
             (domain->conversions != NULL
              ? realloc (domain->conversions,
                       (nconversions + 1) * sizeof (struct converted_domain))
              : malloc ((nconversions + 1) * sizeof (struct converted_domain)));

           if (__builtin_expect (new_conversions == NULL, 0))
             {
              /* Nothing we can do, no more memory.  We cannot use the
                 translation because it might be encoded incorrectly.  */
             unlock_fail:
              gl_rwlock_unlock (domain->conversions_lock);
              return (char *) -1;
             }

           domain->conversions = new_conversions;

           /* Copy the 'encoding' string to permanent storage.  */
           encoding = strdup (encoding);
           if (__builtin_expect (encoding == NULL, 0))
             /* Nothing we can do, no more memory.  We cannot use the
               translation because it might be encoded incorrectly.  */
             goto unlock_fail;

           convd = &new_conversions[nconversions];
           convd->encoding = encoding;

           /* Find out about the character set the file is encoded with.
              This can be found (in textual form) in the entry "".  If this
              entry does not exist or if this does not contain the 'charset='
              information, we will assume the charset matches the one the
              current locale and we don't have to perform any conversion.  */
# ifdef _LIBC
           convd->conv = (__gconv_t) -1;
# else
#  if HAVE_ICONV
           convd->conv = (iconv_t) -1;
#  endif
# endif
           {
             char *nullentry;
             size_t nullentrylen;

             /* Get the header entry.  This is a recursion, but it doesn't
               reallocate domain->conversions because we pass
               encoding = NULL or convert = 0, respectively.  */
             nullentry =
# ifdef IN_LIBGLOCALE
              _nl_find_msg (domain_file, domainbinding, NULL, "",
                           &nullentrylen);
# else
              _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
# endif

             if (nullentry != NULL)
              {
                const char *charsetstr;

                charsetstr = strstr (nullentry, "charset=");
                if (charsetstr != NULL)
                  {
                    size_t len;
                    char *charset;
                    const char *outcharset;

                    charsetstr += strlen ("charset=");
                    len = strcspn (charsetstr, " \t\n");

                    charset = (char *) alloca (len + 1);
# if defined _LIBC || HAVE_MEMPCPY
                    *((char *) mempcpy (charset, charsetstr, len)) = '\0';
# else
                    memcpy (charset, charsetstr, len);
                    charset[len] = '\0';
# endif

                    outcharset = encoding;

# ifdef _LIBC
                    /* We always want to use transliteration.  */
                    outcharset = norm_add_slashes (outcharset, "TRANSLIT");
                    charset = norm_add_slashes (charset, "");
                    int r = __gconv_open (outcharset, charset, &convd->conv,
                                       GCONV_AVOID_NOCONV);
                    if (__builtin_expect (r != __GCONV_OK, 0))
                     {
                       /* If the output encoding is the same there is
                          nothing to do.  Otherwise do not use the
                          translation at all.  */
                       if (__builtin_expect (r != __GCONV_NULCONV, 1))
                         {
                           gl_rwlock_unlock (domain->conversions_lock);
                           free ((char *) encoding);
                           return NULL;
                         }

                       convd->conv = (__gconv_t) -1;
                     }
# else
#  if HAVE_ICONV
                    /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
                      we want to use transliteration.  */
#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
       || _LIBICONV_VERSION >= 0x0105
                    if (strchr (outcharset, '/') == NULL)
                     {
                       char *tmp;

                       len = strlen (outcharset);
                       tmp = (char *) alloca (len + 10 + 1);
                       memcpy (tmp, outcharset, len);
                       memcpy (tmp + len, "//TRANSLIT", 10 + 1);
                       outcharset = tmp;

                       convd->conv = iconv_open (outcharset, charset);

                       freea (outcharset);
                     }
                    else
#   endif
                     convd->conv = iconv_open (outcharset, charset);
#  endif
# endif

                    freea (charset);
                  }
              }
           }
           convd->conv_tab = NULL;
           /* Here domain->conversions is still == new_conversions.  */
           domain->nconversions++;
         }

       found_convd:
         gl_rwlock_unlock (domain->conversions_lock);
       }

      if (
# ifdef _LIBC
         convd->conv != (__gconv_t) -1
# else
#  if HAVE_ICONV
         convd->conv != (iconv_t) -1
#  endif
# endif
         )
       {
         /* We are supposed to do a conversion.  First allocate an
            appropriate table with the same structure as the table
            of translations in the file, where we can put the pointers
            to the converted strings in.
            There is a slight complication with plural entries.  They
            are represented by consecutive NUL terminated strings.  We
            handle this case by converting RESULTLEN bytes, including
            NULs.  */

         /* This lock primarily protects the memory management variables
            freemem, freemem_size.  It also protects write accesses to
            convd->conv_tab.  It's not worth using a separate lock (such
            as domain->conversions_lock) for this purpose, because when
            modifying convd->conv_tab, we also need to lock freemem,
            freemem_size for most of the time.  */
         __libc_lock_define_initialized (static, lock)

         if (__builtin_expect (convd->conv_tab == NULL, 0))
           {
             __libc_lock_lock (lock);
             if (convd->conv_tab == NULL)
              {
                convd->conv_tab =
                  (char **) calloc (nstrings + domain->n_sysdep_strings,
                                  sizeof (char *));
                if (convd->conv_tab != NULL)
                  goto not_translated_yet;
                /* Mark that we didn't succeed allocating a table.  */
                convd->conv_tab = (char **) -1;
              }
             __libc_lock_unlock (lock);
           }

         if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
           /* Nothing we can do, no more memory.  We cannot use the
              translation because it might be encoded incorrectly.  */
           return (char *) -1;

         if (convd->conv_tab[act] == NULL)
           {
             /* We haven't used this string so far, so it is not
               translated yet.  Do this now.  */
             /* We use a bit more efficient memory handling.
               We allocate always larger blocks which get used over
               time.  This is faster than many small allocations.   */
# define INITIAL_BLOCK_SIZE 4080
             static unsigned char *freemem;
             static size_t freemem_size;

             const unsigned char *inbuf;
             unsigned char *outbuf;
             int malloc_count;
# ifndef _LIBC
             transmem_block_t *transmem_list;
# endif

             __libc_lock_lock (lock);
           not_translated_yet:

             inbuf = (const unsigned char *) result;
             outbuf = freemem + sizeof (size_t);
# ifndef _LIBC
             transmem_list = NULL;
# endif

             malloc_count = 0;
             while (1)
              {
                transmem_block_t *newmem;
# ifdef _LIBC
                size_t non_reversible;
                int res;

                if (freemem_size < sizeof (size_t))
                  goto resize_freemem;

                res = __gconv (convd->conv,
                             &inbuf, inbuf + resultlen,
                             &outbuf,
                             outbuf + freemem_size - sizeof (size_t),
                             &non_reversible);

                if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
                  break;

                if (res != __GCONV_FULL_OUTPUT)
                  {
                    /* We should not use the translation at all, it
                      is incorrectly encoded.  */
                    __libc_lock_unlock (lock);
                    return NULL;
                  }

                inbuf = (const unsigned char *) result;
# else
#  if HAVE_ICONV
                const char *inptr = (const char *) inbuf;
                size_t inleft = resultlen;
                char *outptr = (char *) outbuf;
                size_t outleft;

                if (freemem_size < sizeof (size_t))
                  goto resize_freemem;

                outleft = freemem_size - sizeof (size_t);
                if (iconv (convd->conv,
                          (ICONV_CONST char **) &inptr, &inleft,
                          &outptr, &outleft)
                    != (size_t) (-1))
                  {
                    outbuf = (unsigned char *) outptr;
                    break;
                  }
                if (errno != E2BIG)
                  {
                    __libc_lock_unlock (lock);
                    return NULL;
                  }
#  endif
# endif

              resize_freemem:
                /* We must allocate a new buffer or resize the old one.  */
                if (malloc_count > 0)
                  {
                    ++malloc_count;
                    freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
                    newmem = (transmem_block_t *) realloc (transmem_list,
                                                      freemem_size);
# ifdef _LIBC
                    if (newmem != NULL)
                     transmem_list = transmem_list->next;
                    else
                     {
                       struct transmem_list *old = transmem_list;

                       transmem_list = transmem_list->next;
                       free (old);
                     }
# endif
                  }
                else
                  {
                    malloc_count = 1;
                    freemem_size = INITIAL_BLOCK_SIZE;
                    newmem = (transmem_block_t *) malloc (freemem_size);
                  }
                if (__builtin_expect (newmem == NULL, 0))
                  {
                    freemem = NULL;
                    freemem_size = 0;
                    __libc_lock_unlock (lock);
                    return (char *) -1;
                  }

# ifdef _LIBC
                /* Add the block to the list of blocks we have to free
                   at some point.  */
                newmem->next = transmem_list;
                transmem_list = newmem;

                freemem = (unsigned char *) newmem->data;
                freemem_size -= offsetof (struct transmem_list, data);
# else
                transmem_list = newmem;
                freemem = newmem;
# endif

                outbuf = freemem + sizeof (size_t);
              }

             /* We have now in our buffer a converted string.  Put this
               into the table of conversions.  */
             *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
             convd->conv_tab[act] = (char *) freemem;
             /* Shrink freemem, but keep it aligned.  */
             freemem_size -= outbuf - freemem;
             freemem = outbuf;
             freemem += freemem_size & (alignof (size_t) - 1);
             freemem_size = freemem_size & ~ (alignof (size_t) - 1);

             __libc_lock_unlock (lock);
           }

         /* Now convd->conv_tab[act] contains the translation of all
            the plural variants.  */
         result = convd->conv_tab[act] + sizeof (size_t);
         resultlen = *(size_t *) convd->conv_tab[act];
       }
    }

  /* The result string is converted.  */

#endif /* _LIBC || HAVE_ICONV */

  *lengthp = resultlen;
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* _nl_language_preferences_default ( void  )

Definition at line 236 of file langprefs.c.

{
#if HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.2 or newer */
  {
    /* Cache the preferences list, since CoreFoundation calls are expensive.  */
    static const char *cached_languages;
    static int cache_initialized;

    if (!cache_initialized)
      {
        CFTypeRef preferences =
          CFPreferencesCopyAppValue (CFSTR ("AppleLanguages"),
                                     kCFPreferencesCurrentApplication);
        if (preferences != NULL
            && CFGetTypeID (preferences) == CFArrayGetTypeID ())
          {
            CFArrayRef prefArray = (CFArrayRef)preferences;
            int n = CFArrayGetCount (prefArray);
            char buf[256];
            size_t size = 0;
            int i;

            for (i = 0; i < n; i++)
              {
                CFTypeRef element = CFArrayGetValueAtIndex (prefArray, i);
                if (element != NULL
                    && CFGetTypeID (element) == CFStringGetTypeID ()
                    && CFStringGetCString ((CFStringRef)element,
                                           buf, sizeof (buf),
                                           kCFStringEncodingASCII))
                  {
                    _nl_locale_name_canonicalize (buf);
                    size += strlen (buf) + 1;
                    /* Most GNU programs use msgids in English and don't ship
                       an en.mo message catalog.  Therefore when we see "en"
                       in the preferences list, arrange for gettext() to
                       return the msgid, and ignore all further elements of
                       the preferences list.  */
                    if (strcmp (buf, "en") == 0)
                      break;
                  }
                else
                  break;
              }
            if (size > 0)
              {
                char *languages = (char *) malloc (size);

                if (languages != NULL)
                  {
                    char *p = languages;

                    for (i = 0; i < n; i++)
                      {
                        CFTypeRef element =
                          CFArrayGetValueAtIndex (prefArray, i);
                        if (element != NULL
                            && CFGetTypeID (element) == CFStringGetTypeID ()
                            && CFStringGetCString ((CFStringRef)element,
                                                   buf, sizeof (buf),
                                                   kCFStringEncodingASCII))
                          {
                            _nl_locale_name_canonicalize (buf);
                            strcpy (p, buf);
                            p += strlen (buf);
                            *p++ = ':';
                            if (strcmp (buf, "en") == 0)
                              break;
                          }
                        else
                          break;
                      }
                    *--p = '\0';

                    cached_languages = languages;
                  }
              }
          }
        cache_initialized = 1;
      }
    if (cached_languages != NULL)
      return cached_languages;
  }
#endif

#ifdef WIN32_NATIVE
  {
    /* Cache the preferences list, since computing it is expensive.  */
    static const char *cached_languages;
    static int cache_initialized;

    /* Activate the new code only when the GETTEXT_MUI environment variable is
       set, for the time being, since the new code is not well tested.  */
    if (!cache_initialized && getenv ("GETTEXT_MUI") != NULL)
      {
        const char *languages = NULL;
        HMODULE kernel32 = GetModuleHandle ("kernel32");

        if (kernel32 != NULL)
          languages = _nl_language_preferences_win32_mui (kernel32);

        if (languages == NULL && kernel32 != NULL)
          languages = _nl_language_preferences_win32_ME (kernel32);

        if (languages == NULL)
          languages = _nl_language_preferences_win32_95 ();

        if (languages == NULL && kernel32 != NULL)
          languages = _nl_language_preferences_win32_system (kernel32);

        cached_languages = languages;
        cache_initialized = 1;
      }
    if (cached_languages != NULL)
      return cached_languages;
  }
#endif

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void _nl_load_domain ( struct loaded_l10nfile __domain,
struct binding __domainbinding 
)

Definition at line 780 of file loadmsgcat.c.

{
  __libc_lock_define_initialized_recursive (static, lock)
  int fd = -1;
  size_t size;
#ifdef _LIBC
  struct stat64 st;
#else
  struct stat st;
#endif
  struct mo_file_header *data = (struct mo_file_header *) -1;
  int use_mmap = 0;
  struct loaded_domain *domain;
  int revision;
  const char *nullentry;
  size_t nullentrylen;

  __libc_lock_lock_recursive (lock);
  if (domain_file->decided != 0)
    {
      /* There are two possibilities:

        + this is the same thread calling again during this initialization
          via _nl_find_msg.  We have initialized everything this call needs.

        + this is another thread which tried to initialize this object.
          Not necessary anymore since if the lock is available this
          is finished.
      */
      goto done;
    }

  domain_file->decided = -1;
  domain_file->data = NULL;

  /* Note that it would be useless to store domainbinding in domain_file
     because domainbinding might be == NULL now but != NULL later (after
     a call to bind_textdomain_codeset).  */

  /* If the record does not represent a valid locale the FILENAME
     might be NULL.  This can happen when according to the given
     specification the locale file name is different for XPG and CEN
     syntax.  */
  if (domain_file->filename == NULL)
    goto out;

  /* Try to open the addressed file.  */
  fd = open (domain_file->filename, O_RDONLY | O_BINARY);
  if (fd == -1)
    goto out;

  /* We must know about the size of the file.  */
  if (
#ifdef _LIBC
      __builtin_expect (fstat64 (fd, &st) != 0, 0)
#else
      __builtin_expect (fstat (fd, &st) != 0, 0)
#endif
      || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
      || __builtin_expect (size < sizeof (struct mo_file_header), 0))
    /* Something went wrong.  */
    goto out;

#ifdef HAVE_MMAP
  /* Now we are ready to load the file.  If mmap() is available we try
     this first.  If not available or it failed we try to load it.  */
  data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
                                    MAP_PRIVATE, fd, 0);

  if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
    {
      /* mmap() call was successful.  */
      close (fd);
      fd = -1;
      use_mmap = 1;
    }
#endif

  /* If the data is not yet available (i.e. mmap'ed) we try to load
     it manually.  */
  if (data == (struct mo_file_header *) -1)
    {
      size_t to_read;
      char *read_ptr;

      data = (struct mo_file_header *) malloc (size);
      if (data == NULL)
       goto out;

      to_read = size;
      read_ptr = (char *) data;
      do
       {
         long int nb = (long int) read (fd, read_ptr, to_read);
         if (nb <= 0)
           {
#ifdef EINTR
             if (nb == -1 && errno == EINTR)
              continue;
#endif
             goto out;
           }
         read_ptr += nb;
         to_read -= nb;
       }
      while (to_read > 0);

      close (fd);
      fd = -1;
    }

  /* Using the magic number we can test whether it really is a message
     catalog file.  */
  if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
                     0))
    {
      /* The magic number is wrong: not a message catalog file.  */
#ifdef HAVE_MMAP
      if (use_mmap)
       munmap ((caddr_t) data, size);
      else
#endif
       free (data);
      goto out;
    }

  domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
  if (domain == NULL)
    goto out;
  domain_file->data = domain;

  domain->data = (char *) data;
  domain->use_mmap = use_mmap;
  domain->mmap_size = size;
  domain->must_swap = data->magic != _MAGIC;
  domain->malloced = NULL;

  /* Fill in the information about the available tables.  */
  revision = W (domain->must_swap, data->revision);
  /* We support only the major revisions 0 and 1.  */
  switch (revision >> 16)
    {
    case 0:
    case 1:
      domain->nstrings = W (domain->must_swap, data->nstrings);
      domain->orig_tab = (const struct string_desc *)
       ((char *) data + W (domain->must_swap, data->orig_tab_offset));
      domain->trans_tab = (const struct string_desc *)
       ((char *) data + W (domain->must_swap, data->trans_tab_offset));
      domain->hash_size = W (domain->must_swap, data->hash_tab_size);
      domain->hash_tab =
       (domain->hash_size > 2
        ? (const nls_uint32 *)
          ((char *) data + W (domain->must_swap, data->hash_tab_offset))
        : NULL);
      domain->must_swap_hash_tab = domain->must_swap;

      /* Now dispatch on the minor revision.  */
      switch (revision & 0xffff)
       {
       case 0:
         domain->n_sysdep_strings = 0;
         domain->orig_sysdep_tab = NULL;
         domain->trans_sysdep_tab = NULL;
         break;
       case 1:
       default:
         {
           nls_uint32 n_sysdep_strings;

           if (domain->hash_tab == NULL)
             /* This is invalid.  These minor revisions need a hash table.  */
             goto invalid;

           n_sysdep_strings =
             W (domain->must_swap, data->n_sysdep_strings);
           if (n_sysdep_strings > 0)
             {
              nls_uint32 n_sysdep_segments;
              const struct sysdep_segment *sysdep_segments;
              const char **sysdep_segment_values;
              const nls_uint32 *orig_sysdep_tab;
              const nls_uint32 *trans_sysdep_tab;
              nls_uint32 n_inmem_sysdep_strings;
              size_t memneed;
              char *mem;
              struct sysdep_string_desc *inmem_orig_sysdep_tab;
              struct sysdep_string_desc *inmem_trans_sysdep_tab;
              nls_uint32 *inmem_hash_tab;
              unsigned int i, j;

              /* Get the values of the system dependent segments.  */
              n_sysdep_segments =
                W (domain->must_swap, data->n_sysdep_segments);
              sysdep_segments = (const struct sysdep_segment *)
                ((char *) data
                 + W (domain->must_swap, data->sysdep_segments_offset));
              sysdep_segment_values =
                (const char **)
                alloca (n_sysdep_segments * sizeof (const char *));
              for (i = 0; i < n_sysdep_segments; i++)
                {
                  const char *name =
                    (char *) data
                    + W (domain->must_swap, sysdep_segments[i].offset);
                  nls_uint32 namelen =
                    W (domain->must_swap, sysdep_segments[i].length);

                  if (!(namelen > 0 && name[namelen - 1] == '\0'))
                    {
                     freea (sysdep_segment_values);
                     goto invalid;
                    }

                  sysdep_segment_values[i] = get_sysdep_segment_value (name);
                }

              orig_sysdep_tab = (const nls_uint32 *)
                ((char *) data
                 + W (domain->must_swap, data->orig_sysdep_tab_offset));
              trans_sysdep_tab = (const nls_uint32 *)
                ((char *) data
                 + W (domain->must_swap, data->trans_sysdep_tab_offset));

              /* Compute the amount of additional memory needed for the
                 system dependent strings and the augmented hash table.
                 At the same time, also drop string pairs which refer to
                 an undefined system dependent segment.  */
              n_inmem_sysdep_strings = 0;
              memneed = domain->hash_size * sizeof (nls_uint32);
              for (i = 0; i < n_sysdep_strings; i++)
                {
                  int valid = 1;
                  size_t needs[2];

                  for (j = 0; j < 2; j++)
                    {
                     const struct sysdep_string *sysdep_string =
                       (const struct sysdep_string *)
                       ((char *) data
                        + W (domain->must_swap,
                            j == 0
                            ? orig_sysdep_tab[i]
                            : trans_sysdep_tab[i]));
                     size_t need = 0;
                     const struct segment_pair *p = sysdep_string->segments;

                     if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
                       for (p = sysdep_string->segments;; p++)
                         {
                           nls_uint32 sysdepref;

                           need += W (domain->must_swap, p->segsize);

                           sysdepref = W (domain->must_swap, p->sysdepref);
                           if (sysdepref == SEGMENTS_END)
                            break;

                           if (sysdepref >= n_sysdep_segments)
                            {
                              /* Invalid.  */
                              freea (sysdep_segment_values);
                              goto invalid;
                            }

                           if (sysdep_segment_values[sysdepref] == NULL)
                            {
                              /* This particular string pair is invalid.  */
                              valid = 0;
                              break;
                            }

                           need += strlen (sysdep_segment_values[sysdepref]);
                         }

                     needs[j] = need;
                     if (!valid)
                       break;
                    }

                  if (valid)
                    {
                     n_inmem_sysdep_strings++;
                     memneed += needs[0] + needs[1];
                    }
                }
              memneed += 2 * n_inmem_sysdep_strings
                        * sizeof (struct sysdep_string_desc);

              if (n_inmem_sysdep_strings > 0)
                {
                  unsigned int k;

                  /* Allocate additional memory.  */
                  mem = (char *) malloc (memneed);
                  if (mem == NULL)
                    goto invalid;

                  domain->malloced = mem;
                  inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
                  mem += n_inmem_sysdep_strings
                        * sizeof (struct sysdep_string_desc);
                  inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
                  mem += n_inmem_sysdep_strings
                        * sizeof (struct sysdep_string_desc);
                  inmem_hash_tab = (nls_uint32 *) mem;
                  mem += domain->hash_size * sizeof (nls_uint32);

                  /* Compute the system dependent strings.  */
                  k = 0;
                  for (i = 0; i < n_sysdep_strings; i++)
                    {
                     int valid = 1;

                     for (j = 0; j < 2; j++)
                       {
                         const struct sysdep_string *sysdep_string =
                           (const struct sysdep_string *)
                           ((char *) data
                            + W (domain->must_swap,
                                j == 0
                                ? orig_sysdep_tab[i]
                                : trans_sysdep_tab[i]));
                         const struct segment_pair *p =
                           sysdep_string->segments;

                         if (W (domain->must_swap, p->sysdepref)
                            != SEGMENTS_END)
                           for (p = sysdep_string->segments;; p++)
                            {
                              nls_uint32 sysdepref;

                              sysdepref =
                                W (domain->must_swap, p->sysdepref);
                              if (sysdepref == SEGMENTS_END)
                                break;

                              if (sysdep_segment_values[sysdepref] == NULL)
                                {
                                  /* This particular string pair is
                                    invalid.  */
                                  valid = 0;
                                  break;
                                }
                            }

                         if (!valid)
                           break;
                       }

                     if (valid)
                       {
                         for (j = 0; j < 2; j++)
                           {
                            const struct sysdep_string *sysdep_string =
                              (const struct sysdep_string *)
                              ((char *) data
                               + W (domain->must_swap,
                                   j == 0
                                   ? orig_sysdep_tab[i]
                                   : trans_sysdep_tab[i]));
                            const char *static_segments =
                              (char *) data
                              + W (domain->must_swap, sysdep_string->offset);
                            const struct segment_pair *p =
                              sysdep_string->segments;

                            /* Concatenate the segments, and fill
                               inmem_orig_sysdep_tab[k] (for j == 0) and
                               inmem_trans_sysdep_tab[k] (for j == 1).  */

                            struct sysdep_string_desc *inmem_tab_entry =
                              (j == 0
                               ? inmem_orig_sysdep_tab
                               : inmem_trans_sysdep_tab)
                              + k;

                            if (W (domain->must_swap, p->sysdepref)
                                == SEGMENTS_END)
                              {
                                /* Only one static segment.  */
                                inmem_tab_entry->length =
                                  W (domain->must_swap, p->segsize);
                                inmem_tab_entry->pointer = static_segments;
                              }
                            else
                              {
                                inmem_tab_entry->pointer = mem;

                                for (p = sysdep_string->segments;; p++)
                                  {
                                   nls_uint32 segsize =
                                     W (domain->must_swap, p->segsize);
                                   nls_uint32 sysdepref =
                                     W (domain->must_swap, p->sysdepref);
                                   size_t n;

                                   if (segsize > 0)
                                     {
                                       memcpy (mem, static_segments, segsize);
                                       mem += segsize;
                                       static_segments += segsize;
                                     }

                                   if (sysdepref == SEGMENTS_END)
                                     break;

                                   n = strlen (sysdep_segment_values[sysdepref]);
                                   memcpy (mem, sysdep_segment_values[sysdepref], n);
                                   mem += n;
                                  }

                                inmem_tab_entry->length =
                                  mem - inmem_tab_entry->pointer;
                              }
                           }

                         k++;
                       }
                    }
                  if (k != n_inmem_sysdep_strings)
                    abort ();

                  /* Compute the augmented hash table.  */
                  for (i = 0; i < domain->hash_size; i++)
                    inmem_hash_tab[i] =
                     W (domain->must_swap_hash_tab, domain->hash_tab[i]);
                  for (i = 0; i < n_inmem_sysdep_strings; i++)
                    {
                     const char *msgid = inmem_orig_sysdep_tab[i].pointer;
                     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));

                     for (;;)
                       {
                         if (inmem_hash_tab[idx] == 0)
                           {
                            /* Hash table entry is empty.  Use it.  */
                            inmem_hash_tab[idx] = 1 + domain->nstrings + i;
                            break;
                           }

                         if (idx >= domain->hash_size - incr)
                           idx -= domain->hash_size - incr;
                         else
                           idx += incr;
                       }
                    }

                  domain->n_sysdep_strings = n_inmem_sysdep_strings;
                  domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
                  domain->trans_sysdep_tab = inmem_trans_sysdep_tab;

                  domain->hash_tab = inmem_hash_tab;
                  domain->must_swap_hash_tab = 0;
                }
              else
                {
                  domain->n_sysdep_strings = 0;
                  domain->orig_sysdep_tab = NULL;
                  domain->trans_sysdep_tab = NULL;
                }

              freea (sysdep_segment_values);
             }
           else
             {
              domain->n_sysdep_strings = 0;
              domain->orig_sysdep_tab = NULL;
              domain->trans_sysdep_tab = NULL;
             }
         }
         break;
       }
      break;
    default:
      /* This is an invalid revision.  */
    invalid:
      /* This is an invalid .mo file.  */
      free (domain->malloced);
#ifdef HAVE_MMAP
      if (use_mmap)
       munmap ((caddr_t) data, size);
      else
#endif
       free (data);
      free (domain);
      domain_file->data = NULL;
      goto out;
    }

  /* No caches of converted translations so far.  */
  domain->conversions = NULL;
  domain->nconversions = 0;
  gl_rwlock_init (domain->conversions_lock);

  /* Get the header entry and look for a plural specification.  */
#ifdef IN_LIBGLOCALE
  nullentry =
    _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
#else
  nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
#endif
  EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);

 out:
  if (fd != -1)
    close (fd);

  domain_file->decided = 1;

 done:
  __libc_lock_unlock_recursive (lock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void _nl_locale_name_canonicalize ( char *  name)

Here is the caller graph for this function:

const char* _nl_locale_name_default ( void  )

Here is the caller graph for this function:

const char* _nl_locale_name_environ ( int  category,
const char *  categoryname 
)
const char* _nl_locale_name_posix ( int  category,
const char *  categoryname 
)

Here is the caller graph for this function:

const char* _nl_locale_name_thread_unsafe ( int  category,
const char *  categoryname 
)

Here is the caller graph for this function:

char* libintl_dcigettext ( const char *  __domainname,
const char *  __msgid1,
const char *  __msgid2,
int  __plural,
unsigned long int  __n,
int  __category 
)

Variable Documentation

const char _nl_default_dirname[]

Definition at line 335 of file dcigettext.c.

Definition at line 344 of file dcigettext.c.

Definition at line 506 of file loadmsgcat.c.

Definition at line 307 of file gettextP.h.

Definition at line 121 of file gettextP.h.