home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / tar-1.11.8-src.tgz / tar.out / fsf / tar / intl / dcgettext.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  4KB  |  139 lines

  1. /* dcgettext.c -- implemenatation of the dcgettext(3) function
  2.    Copyright (C) 1995 Software Foundation, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. 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
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #ifdef HAVE_CONFIG_H
  19. # include <config.h>
  20. #endif
  21.  
  22. #include <string.h>
  23. #include <sys/types.h>
  24.  
  25. #ifdef HAVE_UNISTD_H
  26. # include <unistd.h>
  27. #endif
  28.  
  29. #include "gettext.h"
  30. #include "gettextP.h"
  31. #include "libgettext.h"
  32. #include "hash-string.h"
  33.  
  34. /* @@ end of prolog @@ */
  35.  
  36. /* Name of the default domain used for gettext(3) prior any call to
  37.    textdomain(3).  The default value for this is "messages".  */
  38. const char _nl_default_default_domain[] = "messages";
  39.  
  40. /* Value used as the default domain for gettext(3).  */
  41. const char *_nl_current_default_domain = _nl_default_default_domain;
  42.  
  43.  
  44. /* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
  45.    locale.  */
  46. char *
  47. dcgettext (domainname, msgid, category)
  48.      const char *domainname;
  49.      const char *msgid;
  50.      int category;
  51. {
  52.   struct loaded_domain *domain;
  53.   size_t top, act, bottom;
  54.   int cmp_val;
  55.  
  56.   /* If no real MSGID is given return NULL.  */
  57.   if (msgid == NULL)
  58.     return NULL;
  59.  
  60.   /* If DOMAINNAME is NULL, we are interested in the default domain.  If
  61.      CATEGORY is not LC_MESSAGES this might not make much sense but the
  62.      defintion left this undefined.  */
  63.   if (domainname == NULL)
  64.     domainname = _nl_current_default_domain;
  65.  
  66.   /* Find structure describing the message catalog matching the
  67.      DOMAINNAME and CATEGORY.  */
  68.   domain = _nl_find_domain (domainname, category);
  69.  
  70.   if (domain == NULL || domain->data == NULL)
  71.     /* No message catalog found.  */
  72.     return (char *) msgid;
  73.  
  74.   /* Locate the MSGID and its translation.  */
  75.   if (domain->hash_size > 0 && domain->hash_tab != NULL)
  76.     {
  77.       /* Use the hashing table.  */
  78.       nls_uint32 len = strlen (msgid);
  79.       nls_uint32 hash_val = hash_string (msgid);
  80.       nls_uint32 idx = hash_val % domain->hash_size;
  81.       nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
  82.       nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]);
  83.  
  84.       if (nstr == 0)
  85.         /* Hash table entry is empty.  */
  86.         return (char *) msgid;
  87.  
  88.       if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
  89.           && strcmp (msgid,
  90.              domain->data + W (domain->must_swap,
  91.                        domain->orig_tab[nstr - 1].offset)) == 0)
  92.       return (char *) domain->data + W (domain->must_swap,
  93.                         domain->trans_tab[nstr - 1].offset);
  94.  
  95.       while (1)
  96.     {
  97.       if (idx >= W (domain->must_swap, domain->hash_size) - incr)
  98.         idx -= W (domain->must_swap, domain->hash_size) - incr;
  99.       else
  100.         idx += incr;
  101.  
  102.       nstr = W (domain->must_swap, domain->hash_tab[idx]);
  103.       if (nstr == 0)
  104.         /* Hash table entry is empty.  */
  105.         return (char *) msgid;
  106.  
  107.       if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len
  108.           && strcmp (msgid,
  109.              domain->data + W (domain->must_swap,
  110.                        domain->orig_tab[nstr - 1].offset))
  111.          == 0)
  112.         return (char *) domain->data
  113.            + W (domain->must_swap, domain->trans_tab[nstr - 1].offset);
  114.     }
  115.       /* NOTREACHED */
  116.     }
  117.  
  118.   /* Now we try the default method:  binary search in the sorted
  119.      array of messages.  */
  120.   bottom = 0;
  121.   top = domain->nstrings;
  122.   while (bottom < top)
  123.     {
  124.       act = (bottom + top) / 2;
  125.       cmp_val = strcmp (msgid, domain->data + W (domain->must_swap,
  126.                          domain->orig_tab[act].offset));
  127.       if (cmp_val < 0)
  128.     top = act;
  129.       else if (cmp_val > 0)
  130.     bottom = act + 1;
  131.       else
  132.     break;
  133.     }
  134.  
  135.   return bottom >= top ? (char *) msgid
  136.      : (char *) domain->data
  137.        + W (domain->must_swap, domain->trans_tab[act].offset);
  138. }
  139.