Update.
authorUlrich Drepper <drepper@redhat.com>
Fri, 24 Dec 1999 05:42:34 +0000 (05:42 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 24 Dec 1999 05:42:34 +0000 (05:42 +0000)
1999-12-23  Ulrich Drepper  <drepper@cygnus.com>

* locale/en_BW: New file.
* locale/en_ZW: New file.
Contributed by Schalk W. Cronjé <schalkc@ntaba.co.za>.

Contributed by Schalk W. Cronjé <schalkc@ntaba.co.za>.

13 files changed:
NAMESPACE
intl/gettextP.h
intl/libintl.h
locale/C-collate.c
locale/categories.def
locale/iso-4217.def
locale/langinfo.h
locale/lc-collate.c
locale/localeinfo.h
locale/programs/ld-collate.c
locale/programs/ld-monetary.c
locale/setlocale.c
localedata/ChangeLog

index 326972d13c0afc79893af7950ccccdd7f8f1f3a2..9a13a557c01b872924ca8fa864d9c3f18823178a 100644 (file)
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -6,6 +6,7 @@ complex.h       cerf{,f,l}, cerfc{,f,l}, cexp2{,f,l},
                clog2{,f,l}, clgamma{,f,l}, ctgamma{,f,l}
 ctype.h                is[a-z], to[a-z]
 dirent.h       d_
+dlfcn.h                RTLD_
 errno.h                E
 fcntl.h                l_
 glob.h         gl_, GLOB_
index 1b4dcb3e07ec8af79db1e9e45f72053b6f87ace5..b3c8c18598a7f6e34b78ee7589f2cd0d879cee74 100644 (file)
@@ -92,6 +92,8 @@ struct binding
   char *dirname;
 };
 
+extern int _nl_msg_cat_cntr;
+
 struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
                                                 char *__locale,
                                                 const char *__domainname))
index 0c987e7d736d1dce3093f61336b4611d25e1c51f..10c3726b7c4d941f54aa456076fcad5e6a9b344e 100644 (file)
@@ -82,34 +82,7 @@ extern char *bindtextdomain (__const char *__domainname,
 # define dgettext(domainname, msgid)                                         \
   dcgettext (domainname, msgid, LC_MESSAGES)
 
-# if __GLIBC__ >= 2 && __GNUC_PREREQ (2,7)
-/* Variable defined in loadmsgcat.c which gets incremented every time a
-   new catalog is loaded.  */
-extern int _nl_msg_cat_cntr;
-
-#  define dcgettext(domainname, msgid, category)                             \
-  (__extension__                                                             \
-   ({                                                                        \
-     char *__result;                                                         \
-     if (__builtin_constant_p (msgid))                                       \
-       {                                                                     \
-        static char *__translation__;                                        \
-        static int __catalog_counter__;                                      \
-        if (! __translation__ || __catalog_counter__ != _nl_msg_cat_cntr)    \
-          {                                                                  \
-            __translation__ =                                                \
-              __dcgettext ((domainname), (msgid), (category));               \
-            __catalog_counter__ = _nl_msg_cat_cntr;                          \
-          }                                                                  \
-        __result = __translation__;                                          \
-       }                                                                     \
-     else                                                                    \
-       __result = __dcgettext ((domainname), (msgid), (category));           \
-     __result;                                                               \
-    }))
-# endif
-#endif /* Optimizing. */
-
+#endif /* Optimizing.  */
 
 __END_DECLS
 
index 6fd0e721be8d7ebdca2ed432f7c6dbc3a584553f..94f6e0f60f1d84dcc895026f553f07c9ba9beea2 100644 (file)
 #include <endian.h>
 #include "localeinfo.h"
 
+#if 0
 /* These tables' entries contain values which make the function behave
    according to POSIX.2 Table 2-8 ``LC_COLLATE Category Definition in
    the POSIX Locale''.  */
 
-const u_int32_t _nl_C_LC_COLLATE_symbol_hash[446] =
+const uint32_t _nl_C_LC_COLLATE_symbol_hash[446] =
 {
   0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
   0xffffffffu, 0xffffffffu, 0x00000154u, 0x00000060u, 0xffffffffu, 0xffffffffu,
@@ -123,7 +124,7 @@ const char _nl_C_LC_COLLATE_symbol_strings[732] =
   "r\0" "s\0" "t\0" "u\0" "v\0" "w\0" "x\0" "y\0" "z\0" "left-curly-bracket\0"
   "vertical-line\0" "right-curly-bracket\0" "tilde\0" "DEL\0";
 
-const u_int32_t _nl_C_LC_COLLATE_symbol_classes[256] =
+const uint32_t _nl_C_LC_COLLATE_symbol_classes[256] =
 {
   1,   0, 1,   1, 1,   2, 1,   3, 1,   4, 1,   5, 1,   6, 1,   7,
   1,   8, 1,   9, 1,  10, 1,  11, 1,  12, 1,  13, 1,  14, 1,  15,
@@ -142,43 +143,19 @@ const u_int32_t _nl_C_LC_COLLATE_symbol_classes[256] =
   1, 112, 1, 113, 1, 114, 1, 115, 1, 116, 1, 117, 1, 118, 1, 119,
   1, 120, 1, 121, 1, 122, 1, 123, 1, 124, 1, 125, 1, 126, 1, 127
 };
+#endif
 
 const struct locale_data _nl_C_LC_COLLATE =
 {
   _nl_C_name,
   NULL, 0, 0, /* no file mapped */
   UNDELETABLE,
-  30,
+  5,
   {
     { word: 0 },
     { string: NULL },
-    { word: 0 },
-    { word: 0 },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { word: 0 },
-    { word: 0 },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { word: 0 },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { string: NULL },
-    { word: 223 },
-    { string: (const char *) _nl_C_LC_COLLATE_symbol_hash },
-    { string: _nl_C_LC_COLLATE_symbol_strings },
     { string: NULL },
     { string: NULL },
-    { string: (const char *) _nl_C_LC_COLLATE_symbol_classes }
+    { string: NULL }
   }
 };
index d94840c5c2424042bbf6b056bf4c80dfd5a18de0..06d79ed202dde68b7cbd7dda492f87b2bf3df6c7 100644 (file)
@@ -43,6 +43,10 @@ DEFINE_CATEGORY
  LC_COLLATE, "LC_COLLATE",
  (
   DEFINE_ELEMENT (_NL_COLLATE_NRULES,         "collate-nrules",           std, word)
+  DEFINE_ELEMENT (_NL_COLLATE_RULESETS,       "collate-rulesets",         std, string)
+  DEFINE_ELEMENT (_NL_COLLATE_TABLEMB,        "collate-tablemb",          std, string)
+  DEFINE_ELEMENT (_NL_COLLATE_WEIGHTMB,       "collate-weightmb",         std, string)
+  DEFINE_ELEMENT (_NL_COLLATE_EXTRAMB,        "collate-extramb",          std, string)
   ), _nl_postload_collate)
 
 
index bd777639e0ba7be5f79496c381035a076d7bea12..d35def61a2fba64ac64b48cd334d3f3d90c5dadb 100644 (file)
@@ -12,14 +12,13 @@ DEFINE_INT_CURR("AFA ")             /* Afghanistan Afgani  */
 DEFINE_INT_CURR("ALL ")                /* Albanian Lek  */
 DEFINE_INT_CURR("AMD ")                /* Armenia Dram  */
 DEFINE_INT_CURR("ANG ")                /* Netherlands Antilles  */
-DEFINE_INT_CURR("AOK ")                /* Angolan Kwanza  */ /* obsolete */
 DEFINE_INT_CURR("AON ")                /* Angolan New Kwanza  */
 DEFINE_INT_CURR("ARS ")                /* Argentine Peso  */
 DEFINE_INT_CURR("ATS ")                /* Austrian Schilling  */
 DEFINE_INT_CURR("AUD ")                /* Australian Dollar  */
 DEFINE_INT_CURR("AWG ")                /* Aruba Guilder  */
 DEFINE_INT_CURR("AZM ")                /* Azerbaijan Manat  */
-DEFINE_INT_CURR("BAD ")                /* Bosnian Dinar  */
+DEFINE_INT_CURR("BAK ")                /* Bosnian and Herzegovina Convertible Mark  */
 DEFINE_INT_CURR("BBD ")                /* Barbados Dollar  */
 DEFINE_INT_CURR("BDT ")                /* Bangladesh Taka  */
 DEFINE_INT_CURR("BEF ")                /* Belgian Franc  */
@@ -32,7 +31,6 @@ DEFINE_INT_CURR("BOB ")               /* Bolivian Boliviano  */
 DEFINE_INT_CURR("BPS ")                /* Canton and Enderbury Islands  */ /* ?? */
 DEFINE_INT_CURR("BRE ")                /* Brazil Real  */ /* obsolete */
 DEFINE_INT_CURR("BRL ")                /* Brazil Cruzeiro  */
-DEFINE_INT_CURR("BRR ")                /* Brazil Real  */ /* obsolete */
 DEFINE_INT_CURR("BSD ")                /* Bahamas Dollar  */
 DEFINE_INT_CURR("BTN ")                /* Bhutan Ngultrum  */
 DEFINE_INT_CURR("BUK ")                /* Burma  */ /* obsolete */
@@ -129,6 +127,7 @@ DEFINE_INT_CURR("MWK ")             /* Malawi Kwacha  */
 DEFINE_INT_CURR("MXP ")                /* Mexican Peso  */
 DEFINE_INT_CURR("MYR ")                /* Malaysian Ringgit  */
 DEFINE_INT_CURR("MZM ")                /* Mozambique Metical  */
+DEFINE_INT_CURR("NAD ")                /* Namibia Dollar  */
 DEFINE_INT_CURR("NGN ")                /* Nigeria Naira  */
 DEFINE_INT_CURR("NIC ")                /* Nicaragua Cordoba  */
 DEFINE_INT_CURR("NLG ")                /* Netherlands Guilder  */
index 44f406470868c015f7aff38914b9909eba046a66..ff48fab35f2b906611ead7277a139aaf9828283a 100644 (file)
@@ -231,26 +231,10 @@ enum
      This information is accessed by the strcoll and strxfrm functions.
      These `nl_langinfo' names are used only internally.  */
   _NL_COLLATE_NRULES = _NL_ITEM (LC_COLLATE, 0),
-#if 0
+  _NL_COLLATE_RULESETS,
   _NL_COLLATE_TABLEMB,
-  _NL_COLLATE_HASH_SIZE,
-  _NL_COLLATE_HASH_LAYERS,
-  _NL_COLLATE_TABLEWC,
-  _NL_COLLATE_UNDEFINED_WC,
+  _NL_COLLATE_WEIGHTMB,
   _NL_COLLATE_EXTRAMB,
-  _NL_COLLATE_EXTRAWC,
-  _NL_COLLATE_ELEM_HASH_SIZE,
-  _NL_COLLATE_ELEM_HASH,
-  _NL_COLLATE_ELEM_STR_POOL,
-  _NL_COLLATE_ELEM_VAL,
-  _NL_COLLATE_ELEM_VALMB,
-  _NL_COLLATE_ELEM_VALWC,
-  _NL_COLLATE_SYMB_HASH_SIZE,
-  _NL_COLLATE_SYMB_HASH,
-  _NL_COLLATE_SYMB_STR_POOL,
-  _NL_COLLATE_SYMB_CLASSMB,
-  _NL_COLLATE_SYMB_CLASSWC,
-#endif
   _NL_NUM_LC_COLLATE,
 
   /* LC_CTYPE category: character classification.
index c448e1079d6beb2b87f9fe908c377348f182f40e..02262b5ce27138f6c110b5c8a57a7c6ebe38b1b8 100644 (file)
 #include <endian.h>
 
 
-extern const u_int32_t _nl_C_LC_COLLATE_symbol_hash[];
-extern const char _nl_C_LC_COLLATE_symbol_strings[];
-extern const u_int32_t _nl_C_LC_COLLATE_symbol_classes[];
-
-
 _NL_CURRENT_DEFINE (LC_COLLATE);
 
-const u_int32_t *__collate_tablewc;
-const u_int32_t *__collate_extrawc;
-
-const u_int32_t *__collate_element_hash;
-const char *__collate_element_strings;
-const uint32_t *__collate_element_values;
-
-const u_int32_t *__collate_symbol_hash = _nl_C_LC_COLLATE_symbol_hash;
-const char *__collate_symbol_strings = _nl_C_LC_COLLATE_symbol_strings;
-const u_int32_t *__collate_symbol_classeswc = _nl_C_LC_COLLATE_symbol_classes;
-
+const int32_t *__collate_tablemb;
+const unsigned char *__collate_weightmb;
+const unsigned char *__collate_extramb;
 
 /* We are called after loading LC_CTYPE data to load it into
    the variables used by the collation functions and regex.  */
 void
 _nl_postload_collate (void)
 {
-#if 0
-  /* XXX For now */
 #define paste(a,b) paste1(a,b)
 #define paste1(a,b) a##b
+#define current(x) _NL_CURRENT (LC_COLLATE, paste(_NL_COLLATE_,x))
 
-#define current(x)                                                           \
-  ((const unsigned int *) _NL_CURRENT (LC_COLLATE, paste(_NL_COLLATE_,x)))
-
-  __collate_tablewc = current (TABLEWC);
-  __collate_extrawc = current (EXTRAWC);
-
-  __collate_element_hash = current (ELEM_HASH);
-  __collate_element_strings = (const char *) current (ELEM_STR_POOL);
-  __collate_element_values = (const uint32_t *) current (ELEM_VAL);
-
-  __collate_symbol_hash = current (SYMB_HASH);
-  __collate_symbol_strings = (const char *) current (SYMB_STR_POOL);
-  __collate_symbol_classeswc = current (SYMB_CLASSWC);
-#endif
+  __collate_tablemb = (const int32_t *) current (TABLEMB);
+  __collate_weightmb = (const unsigned char *) current (WEIGHTMB);
+  __collate_extramb = (const unsigned char *) current (EXTRAMB);
 }
index c72ea9d84d9c7eef3990446d0c55168b706114f3..078e205f4ff0a7accd095319ead796dc1196f50b 100644 (file)
@@ -36,9 +36,7 @@
 #define        LIMAGIC(category)       (0x980505 ^ (category))
 
 /* Two special weight constants for the collation data.  */
-#define FORWARD_CHAR ((uint32_t) 0xfffffffd)
-#define ELLIPSIS_CHAR ((uint32_t) 0xfffffffe)
-#define IGNORE_CHAR ((uint32_t) 0xffffffff)
+#define IGNORE_CHAR    2
 
 /* We use a special value for the usage counter in `locale_data' to
    signal that this data must never be removed anymore.  */
@@ -184,13 +182,8 @@ extern const wchar_t *_nl_get_walt_digit (unsigned int number);
 
 
 /* Global variables for LC_COLLATE category data.  */
-extern const uint32_t *__collate_tablewc;
-extern const uint32_t *__collate_extrawc;
-extern const uint32_t *__collate_element_hash;
-extern const char *__collate_element_strings;
-extern const uint32_t *__collate_element_values;
-extern const uint32_t *__collate_symbol_hash;
-extern const char *__collate_symbol_strings;
-extern const uint32_t *__collate_symbol_classes;
+extern const int32_t *__collate_tablemb;
+extern const unsigned char *__collate_extrweightmb;
+extern const unsigned char *__collate_extramb;
 
 #endif /* localeinfo.h */
index 52c4e3c6a18e4a108ec55fc4010c71c0c0a8c746..a0f1139cdee13b52bfbabb6b613cb9d564d44271 100644 (file)
@@ -54,6 +54,8 @@ struct section_list
   struct element_t *last;
   /* These are the rules for this section.  */
   enum coll_sort_rule *rules;
+  /* Index of the rule set in the appropriate section of the output file.  */
+  int ruleidx;
 };
 
 struct element_t;
@@ -72,7 +74,9 @@ struct element_t
   const char *name;
 
   const char *mbs;
+  size_t nmbs;
   const uint32_t *wcs;
+  size_t nwcs;
   int *mborder;
   int wcorder;
 
@@ -175,6 +179,55 @@ struct locale_collate_t
 static int nrules;
 
 
+/* These are definitions used by some of the functions for handling
+   UTF-8 encoding below.  */
+static const uint32_t encoding_mask[] =
+{
+  ~0x7ff, ~0xffff, ~0x1fffff, ~0x3ffffff
+};
+
+static const unsigned char encoding_byte[] =
+{
+  0xc0, 0xe0, 0xf0, 0xf8, 0xfc
+};
+
+
+/* We need UTF-8 encoding of numbers.  */
+static inline int
+utf8_encode (char *buf, int val)
+{
+  char *startp = buf;
+  int retval;
+
+  if (val < 0x80)
+    {
+      *buf++ = (char) val;
+      retval = 1;
+    }
+  else
+    {
+      int step;
+
+      for (step = 2; step < 6; ++step)
+       if ((val & encoding_mask[step - 2]) == 0)
+         break;
+      retval = step;
+
+      *buf = encoding_byte[step - 2];
+      --step;
+      do
+       {
+         buf[step] = 0x80 | (val & 0x3f);
+         val >>= 6;
+       }
+      while (--step > 0);
+      *buf |= val;
+    }
+
+  return buf - startp;
+}
+
+
 static struct section_list *
 make_seclist_elem (struct locale_collate_t *collate, const char *string,
                   struct section_list *next)
@@ -202,19 +255,29 @@ new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen,
   newp->name = name == NULL ? NULL : obstack_copy0 (&collate->mempool,
                                                    name, namelen);
   if (mbs != NULL)
-    newp->mbs = obstack_copy0 (&collate->mempool, mbs, mbslen);
+    {
+      newp->mbs = obstack_copy0 (&collate->mempool, mbs, mbslen);
+      newp->nmbs = mbslen;
+    }
   else
-    newp->mbs = NULL;
+    {
+      newp->mbs = NULL;
+      newp->nmbs = 0;
+    }
   if (wcs != NULL)
     {
-      size_t nwcs = wcslen ((wchar_t *) wcs) + 1;
+      size_t nwcs = wcslen ((wchar_t *) wcs);
       uint32_t zero = 0;
       obstack_grow (&collate->mempool, wcs, nwcs * sizeof (uint32_t));
       obstack_grow (&collate->mempool, &zero, sizeof (uint32_t));
       newp->wcs = (uint32_t *) obstack_finish (&collate->mempool);
+      newp->nwcs = nwcs;
     }
   else
-    newp->wcs = NULL;
+    {
+      newp->wcs = NULL;
+      newp->nwcs = 0;
+    }
   newp->mborder = NULL;
   newp->wcorder = 0;
   newp->used_in_level = 0;
@@ -225,7 +288,7 @@ new_element (struct locale_collate_t *collate, const char *mbs, size_t mbslen,
   newp->file = NULL;
   newp->line = 0;
 
-  newp->section = NULL;
+  newp->section = collate->current_section;
 
   newp->last = NULL;
   newp->next = NULL;
@@ -532,6 +595,7 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
   elem->line = ldfile->lineno;
   elem->last = collate->cursor;
   elem->next = collate->cursor ? collate->cursor->next : NULL;
+  elem->section = collate->current_section;
   if (collate->cursor != NULL)
     collate->cursor->next = elem;
   if (collate->start == NULL)
@@ -801,6 +865,25 @@ insert_value (struct linereader *ldfile, struct token *arg,
            /* This cannot happen.  */
            assert (! "Internal error");
        }
+      else
+       {
+         /* Maybe the character was used before the definition.  In this case
+            we have to insert the byte sequences now.  */
+         if (elem->mbs == NULL && seq != NULL)
+           {
+             elem->mbs = obstack_copy0 (&collate->mempool,
+                                        seq->bytes, seq->nbytes);
+             elem->nmbs = seq->nbytes;
+           }
+
+         if (elem->wcs == NULL && seq != ILLEGAL_CHAR_VALUE)
+           {
+             uint32_t wcs[2] = { wc, 0 };
+
+             elem->wcs = obstack_copy (&collate->mempool, wcs, sizeof (wcs));
+             elem->nwcs = 1;
+           }
+       }
     }
 
   /* Test whether this element is not already in the list.  */
@@ -808,7 +891,7 @@ insert_value (struct linereader *ldfile, struct token *arg,
                             && elem->next == collate->cursor))
     {
       lr_error (ldfile, _("order for `%.*s' already defined at %s:%zu"),
-               arg->val.str.lenmb, arg->val.str.startmb,
+               (int) arg->val.str.lenmb, arg->val.str.startmb,
                elem->file, elem->line);
       lr_ignore_rest (ldfile, 0);
       return 1;
@@ -866,8 +949,8 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
         sequences for the first and end character must be the same.
         This is mainly to prevent unwanted effects and this is often
         not what is wanted.  */
-      size_t len = (startp->mbs != NULL ? strlen (startp->mbs)
-                   : (endp->mbs != NULL ? strlen (endp->mbs) : 0));
+      size_t len = (startp->mbs != NULL ? startp->nmbs
+                   : (endp->mbs != NULL ? endp->nmbs : 0));
       char mbcnt[len + 1];
       char mbend[len + 1];
 
@@ -878,7 +961,7 @@ handle_ellipsis (struct linereader *ldfile, struct token *arg,
 
       if (startp != NULL && endp != NULL
          && startp->mbs != NULL && endp->mbs != NULL
-         && strlen (startp->mbs) != strlen (endp->mbs))
+         && startp->nmbs != endp->nmbs)
        {
          lr_error (ldfile, _("\
 %s: byte sequences of first and last character must have the same length"),
@@ -974,7 +1057,8 @@ sequence is not lower than that of the last character"), "LC_COLLATE");
                    {
                      lr_error (ldfile, _("\
 order for `%.*s' already defined at %s:%zu"),
-                               namelen, seq->name, elem->file, elem->line);
+                               (int) namelen, seq->name,
+                               elem->file, elem->line);
                      goto increment;
                    }
 
@@ -1066,7 +1150,7 @@ order for `%.*s' already defined at %s:%zu"),
            invalid_range:
              lr_error (ldfile, _("\
 `%s' and `%.*s' are no valid names for symbolic range"),
-                       startp->name, lento, endp->name);
+                       startp->name, (int) lento, endp->name);
              return;
            }
 
@@ -1112,7 +1196,7 @@ order for `%.*s' already defined at %s:%zu"),
                    {
                      lr_error (ldfile, _("\
 %s: order for `%.*s' already defined at %s:%zu"),
-                               "LC_COLLATE", lenfrom, buf,
+                               "LC_COLLATE", (int) lenfrom, buf,
                                elem->file, elem->line);
                      continue;
                    }
@@ -1160,8 +1244,11 @@ order for `%.*s' already defined at %s:%zu"),
                    {
                      /* Update the element.  */
                      if (seq != NULL)
-                       elem->mbs = obstack_copy0 (&collate->mempool,
-                                                  seq->bytes, seq->nbytes);
+                       {
+                         elem->mbs = obstack_copy0 (&collate->mempool,
+                                                    seq->bytes, seq->nbytes);
+                         elem->nmbs = seq->nbytes;
+                       }
 
                      if (wc != ILLEGAL_CHAR_VALUE)
                        {
@@ -1172,11 +1259,13 @@ order for `%.*s' already defined at %s:%zu"),
                          obstack_grow (&collate->mempool,
                                        &zero, sizeof (uint32_t));
                          elem->wcs = obstack_finish (&collate->mempool);
+                         elem->nwcs = 1;
                        }
                    }
 
                  elem->file = ldfile->fname;
                  elem->line = ldfile->lineno;
+                 elem->section = collate->current_section;
                }
 
              /* Enqueue the new element.  */
@@ -1281,6 +1370,8 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
   struct element_t *runp;
   int i;
   int need_undefined = 0;
+  struct section_list *sect;
+  int ruleidx;
 
   /* If this assertion is hit change the type in `element_t'.  */
   assert (nrules <= sizeof (runp->used_in_level) * 8);
@@ -1327,7 +1418,7 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
      Since at each time only the weights for each of the rules are
      only compared to other weights for this rule it is possible to
      assign more compact weight values than simply counting all
-     weights in sequence.  We can assign weights from 2 one for each
+     weights in sequence.  We can assign weights from 3, one for each
      rule individually and only for those elements, which are actually
      used for this rule.
 
@@ -1336,44 +1427,64 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
      be encoded to make it possible to emit the value as a byte
      string.  */
   for (i = 0; i < nrules; ++i)
-    mbact[i] = 2;
-  wcact = 2;
+    mbact[i] = 3;
+  wcact = 3;
   runp = collate->start;
   while (runp != NULL)
     {
-      if (runp->mbs != NULL)
+      /* Determine the order.  */
+      if (runp->used_in_level != 0)
        {
-         struct element_t **eptr;
+         runp->mborder = (int *) obstack_alloc (&collate->mempool,
+                                                nrules * sizeof (int));
 
-         /* Determine the order.  */
-         if (runp->used_in_level != 0)
-           {
-             runp->mborder = (int *) obstack_alloc (&collate->mempool,
-                                                    nrules * sizeof (int));
+         for (i = 0; i < nrules; ++i)
+           if ((runp->used_in_level & (1 << i)) != 0)
+             runp->mborder[i] = mbact[i]++;
+           else
+             runp->mborder[i] = 0;
+       }
 
-             for (i = 0; i < nrules; ++i)
-               if ((runp->used_in_level & (1 << i)) != 0)
-                 runp->mborder[i] = mbact[i]++;
-               else
-                 runp->mborder[i] = 0;
-           }
+      if (runp->mbs != NULL)
+       {
+         struct element_t **eptr;
 
          /* Find the point where to insert in the list.  */
          eptr = &collate->mbheads[((unsigned char *) runp->mbs)[0]];
          while (*eptr != NULL)
            {
-             /* Check which string is larger, the one we want to insert
-                or the current element of the list we are looking at.  */
-             assert (runp->mbs[0] == (*eptr)->mbs[0]);
-             if (strcmp (runp->mbs, (*eptr)->mbs) > 0)
+             if ((*eptr)->nmbs < runp->nmbs)
                break;
 
+             if ((*eptr)->nmbs == runp->nmbs)
+               {
+                 int c = memcmp ((*eptr)->mbs, runp->mbs, runp->nmbs);
+
+                 if (c == 0)
+                   {
+                     /* This should not happen.  It means that we have
+                        to symbols with the same byte sequence.  It is
+                        of course an error.  */
+                     error_at_line (0, 0, (*eptr)->file, (*eptr)->line,
+                                    _("symbol `%s' has same encoding as"),
+                                    (*eptr)->name);
+                     error_at_line (0, 0, runp->file, runp->line,
+                                    _("symbol `%s'"), runp->name);
+                     goto dont_insert;
+                   }
+                 else if (c < 0)
+                   /* Insert it here.  */
+                   break;
+               }
+
+             /* To the next entry.  */
              eptr = &(*eptr)->mbnext;
            }
 
          /* Set the pointers.  */
          runp->mbnext = *eptr;
          *eptr = runp;
+       dont_insert:
        }
 
       if (runp->wcs != NULL)
@@ -1394,6 +1505,7 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
 
   /* Now determine whether the UNDEFINED entry is needed and if yes,
      whether it was defined.  */
+  collate->undefined.used_in_level = need_undefined ? ~0ul : 0;
   if (need_undefined && collate->undefined.file == NULL)
     {
       error (0, 0, _("no definition of `UNDEFINED'"));
@@ -1407,6 +1519,81 @@ collate_finish (struct localedef_t *locale, struct charmap_t *charmap)
 
       collate->undefined.wcorder = wcact++;
     }
+
+  /* Finally, try to unify the rules for the sections.  Whenever the rules
+     for a section are the same as those for another section give the
+     ruleset the same index.  Since there are never many section we can
+     use an O(n^2) algorithm here.  */
+  sect = collate->sections;
+  assert (sect != NULL);
+  ruleidx = 0;
+  do
+    {
+      struct section_list *osect = collate->sections;
+
+      while (osect != sect)
+       if (memcmp (osect->rules, sect->rules, nrules) == 0)
+         break;
+       else
+         osect = osect->next;
+
+      if (osect == sect)
+       sect->ruleidx = ruleidx++;
+      else
+       sect->ruleidx = osect->ruleidx;
+
+      /* Next section.  */
+      sect = sect->next;
+    }
+  while (sect != NULL);
+  /* We are currently not prepared for more than 256 rulesets.  But this
+     should never really be a problem.  */
+  assert (ruleidx <= 256);
+}
+
+
+static inline int32_t
+output_weight (struct obstack *pool, struct locale_collate_t *collate,
+              struct element_t *elem)
+{
+  size_t cnt;
+  int32_t retval;
+
+  /* Optimize the use of UNDEFINED.  */
+  if (elem == &collate->undefined)
+    /* The weights are already inserted.  */
+    return 0;
+
+  /* This byte can start exactly one collation element and this is
+     a single byte.  We can directly give the index to the weights.  */
+  retval = obstack_object_size (pool);
+
+  /* Construct the weight.  */
+  for (cnt = 0; cnt < nrules; ++cnt)
+    {
+      char buf[elem->weights[cnt].cnt * 7];
+      int len = 0;
+      int i;
+
+      /* Add the direction.  */
+      obstack_1grow (pool, elem->section->rules[cnt]);
+
+      for (i = 0; i < elem->weights[cnt].cnt; ++i)
+       /* Encode the weight value.  */
+       if (elem->weights[cnt].w[i] == NULL)
+         {
+           /* This entry was IGNORE.  */
+           buf[len++] = '\3';
+         }
+       else
+         len += utf8_encode (&buf[len],
+                             elem->weights[cnt].w[i]->mborder[cnt]);
+
+      /* And add the buffer content.  */
+      obstack_grow (pool, buf, len);
+    }
+
+  return retval;
 }
 
 
@@ -1420,6 +1607,15 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
   struct locale_file data;
   uint32_t idx[nelems];
   size_t cnt;
+  size_t ch;
+  int32_t tablemb[256];
+  struct obstack weightpool;
+  struct obstack extrapool;
+  struct section_list *sect;
+  int i;
+
+  obstack_init (&weightpool);
+  obstack_init (&extrapool);
 
   data.magic = LIMAGIC (LC_COLLATE);
   data.n = nelems;
@@ -1438,6 +1634,208 @@ collate_output (struct localedef_t *locale, struct charmap_t *charmap,
   idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
   ++cnt;
 
+  /* Prepare the ruleset table.  */
+  for (sect = collate->sections, i = 0; sect != NULL; sect = sect->next)
+    if (sect->ruleidx == i)
+      {
+       obstack_grow (&weightpool, sect->rules, nrules);
+       ++i;
+      }
+  /* And align the output.  */
+  i = (nrules * i) % __alignof__ (int32_t);
+  if (i > 0)
+    do
+      obstack_1grow (&weightpool, '\0');
+    while (++i < __alignof__ (int32_t));
+
+  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_RULESETS));
+  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);
+  iov[2 + cnt].iov_base = obstack_finish (&weightpool);
+  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
+  ++cnt;
+
+  /* Generate the 8-bit table.  Walk through the lists of sequences
+     starting with the same byte and add them one after the other to
+     the table.  In case we have more than one sequence starting with
+     the same byte we have to use extra indirection.
+
+     First add a record for the NUL byte.  This entry will never be used
+     so it does not matter.  */
+  tablemb[0] = 0;
+
+  /* Now insert the `UNDEFINED' value if it is used.  Since this value
+     will probably be used more than once it is good to store the
+     weights only once.  */
+  if (collate->undefined.used_in_level != 0)
+    output_weight (&weightpool, collate, &collate->undefined);
+
+  for (ch = 1; ch < 256; ++ch)
+    if (collate->mbheads[ch]->mbnext == NULL
+       && collate->mbheads[ch]->nmbs == 1)
+      {
+       tablemb[ch] = output_weight (&weightpool, collate,
+                                     collate->mbheads[ch]);
+      }
+    else
+      {
+       /* The entries in the list are sorted by length and then
+           alphabetically.  This is the order in which we will add the
+           elements to the collation table.  This allows to simply
+           walk the table in sequence and stop at the first matching
+           entry.  Since the longer sequences are coming first in the
+           list they have the possibility to match first, just as it
+           has to be.  In the worst case we are walking to the end of
+           the list where we put, if no singlebyte sequence is defined
+           in the locale definition, the weights for UNDEFINED.
+
+          To reduce the length of the search list we compress them a bit.
+          This happens by collecting sequences of consecutive byte
+          sequences in one entry (having and begin and end byte sequence)
+          and add only one index into the weight table.  We can find the
+          consecutive entries since they are also consecutive in the list.  */
+       struct element_t *runp = collate->mbheads[ch];
+       struct element_t *lastp;
+
+       tablemb[ch] = -obstack_object_size (&extrapool);
+
+       do
+         {
+           /* Store the current index in the weight table.  We know that
+              the current position in the `extrapool' is aligned on a
+              32-bit address.  */
+           int32_t weightidx;
+           int added;
+
+           /* Output the weight info.  */
+           weightidx = output_weight (&weightpool, collate, runp);
+
+           /* Find out wether this is a single entry or we have more than
+              one consecutive entry.  */
+           if (runp->mbnext != NULL
+               && runp->nmbs == runp->mbnext->nmbs
+               && memcmp (runp->mbs, runp->mbnext->mbs, runp->nmbs - 1) == 0
+               && (runp->mbs[runp->nmbs - 1] + 1
+                   == runp->mbnext->mbs[runp->nmbs - 1]))
+             {
+               int i;
+
+               /* More than one consecutive entry.  We mark this by having
+                  a negative index into the weight table.  */
+               weightidx = -weightidx;
+
+               /* Now add first the initial byte sequence.  */
+               added = ((sizeof (int32_t) + 1 + 1 + 2 * (runp->nmbs - 1)
+                         + __alignof__ (int32_t) - 1)
+                        & ~(__alignof__ (int32_t) - 1));
+               obstack_make_room (&extrapool, added);
+
+               if (sizeof (int32_t) == sizeof (int))
+                 obstack_int_grow_fast (&extrapool, weightidx);
+               else
+                 obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
+               obstack_1grow_fast (&extrapool, runp->section->ruleidx);
+               obstack_1grow_fast (&extrapool, runp->nmbs - 1);
+               for (i = 1; i < runp->nmbs; ++i)
+                 obstack_1grow_fast (&extrapool, runp->mbs[i]);
+
+               /* Now find the end of the consecutive sequence.  */
+               do
+                 runp = runp->next;
+               while (runp->mbnext != NULL
+                      && runp->nmbs == runp->mbnext->nmbs
+                      && memcmp (runp->mbs, runp->mbnext->mbs,
+                                 runp->nmbs - 1) == 0
+                      && (runp->mbs[runp->nmbs - 1] + 1
+                          == runp->mbnext->mbs[runp->nmbs - 1]));
+
+               /* And add the end by sequence.  Without length this time.  */
+               for (i = 1; i < runp->nmbs; ++i)
+                 obstack_1grow_fast (&extrapool, runp->mbs[i]);
+             }
+           else
+             {
+               /* A single entry.  Simply add the index and the length and
+                  string (except for the first character which is already
+                  tested for).  */
+               int i;
+
+               added = ((sizeof (int32_t) + 1 + 1 + runp->nmbs - 1
+                         + __alignof__ (int32_t) - 1)
+                        & ~(__alignof__ (int32_t) - 1));
+               obstack_make_room (&extrapool, added);
+
+               if (sizeof (int32_t) == sizeof (int))
+                 obstack_int_grow_fast (&extrapool, weightidx);
+               else
+                 obstack_grow (&extrapool, &weightidx, sizeof (int32_t));
+               obstack_1grow_fast (&extrapool, runp->section->ruleidx);
+               obstack_1grow_fast (&extrapool, runp->nmbs - 1);
+               for (i = 1; i < runp->nmbs; ++i)
+                 obstack_1grow_fast (&extrapool, runp->mbs[i]);
+             }
+
+           /* Add alignment bytes if necessary.  */
+           i = added % __alignof__ (int32_t);
+           if (i > 0)
+             do
+               obstack_1grow_fast (&extrapool, '\0');
+             while (++i != __alignof__ (int32_t));
+
+           /* Next entry.  */
+           lastp = runp;
+           runp = runp->mbnext;
+         }
+       while (runp != NULL);
+
+       /* If the final entry in the list is not a single character we
+           add an UNDEFINED entry here.  */
+       if (lastp->nmbs != 1)
+         {
+           int added = ((sizeof (int32_t) + 1 + 1 + __alignof__ (int32_t))
+                        & ~(__alignof__ (int32_t) - 1));
+           obstack_make_room (&extrapool, added);
+
+           if (sizeof (int32_t) == sizeof (int))
+             obstack_int_grow_fast (&extrapool, 0);
+           else
+             {
+               int32_t zero = 0;
+               obstack_grow (&extrapool, &zero, sizeof (int32_t));
+             }
+           /* XXX What rule? We just pick the first.  */
+           obstack_1grow_fast (&extrapool, 0);
+           /* Length is zero.  */
+           obstack_1grow_fast (&extrapool, 0);
+
+           /* Add alignment bytes if necessary.  */
+           i = added % __alignof__ (int32_t);
+           if (i > 0)
+             do
+               obstack_1grow_fast (&extrapool, '\0');
+             while (++i != __alignof__ (int32_t));
+         }
+      }
+
+  /* Now add the three tables.  */
+  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_TABLEMB));
+  iov[2 + cnt].iov_base = tablemb;
+  iov[2 + cnt].iov_len = sizeof (tablemb);
+  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
+  ++cnt;
+
+  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_WEIGHTMB));
+  iov[2 + cnt].iov_len = obstack_object_size (&weightpool);
+  iov[2 + cnt].iov_base = obstack_finish (&weightpool);
+  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
+  ++cnt;
+
+  assert (cnt == _NL_ITEM_INDEX (_NL_COLLATE_EXTRAMB));
+  iov[2 + cnt].iov_len = obstack_object_size (&extrapool);
+  iov[2 + cnt].iov_base = obstack_finish (&extrapool);
+  idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
+  ++cnt;
+
+
   assert (cnt == _NL_ITEM_INDEX (_NL_NUM_LC_COLLATE));
 
   write_locale_data (output_path, "LC_COLLATE", 2 + cnt, iov);
@@ -1859,6 +2257,12 @@ error while adding equivalent collating symbol"));
                            "LC_COLLATE", arg->val.str.startmb);
                  /* We use the error section.  */
                  collate->current_section = &collate->error_section;
+
+                 if (collate->error_section.first == NULL)
+                   {
+                     collate->error_section.next = collate->sections;
+                     collate->sections = &collate->error_section;
+                   }
                }
              else
                {
@@ -1871,6 +2275,11 @@ error while adding equivalent collating symbol"));
                    lr_error (ldfile, _("\
 %s: multiple order definitions for section `%s'"),
                              "LC_COLLATE", sp->name);
+                 else
+                   {
+                     sp->next = collate->sections;
+                     collate->sections = sp;
+                   }
 
                  /* Next should come the end of the line or a semicolon.  */
                  arg = lr_token (ldfile, charmap, repertoire);
@@ -1909,6 +2318,11 @@ error while adding equivalent collating symbol"));
                lr_error (ldfile, _("\
 %s: multiple order definitions for unnamed section"),
                          "LC_COLLATE");
+             else
+               {
+                 collate->unnamed_section.next = collate->sections;
+                 collate->sections = &collate->unnamed_section;
+               }
            }
 
          /* Now read the direction names.  */
@@ -1987,7 +2401,7 @@ error while adding equivalent collating symbol"));
                      insert does not exist.  */
                  lr_error (ldfile, _("\
 %s: cannot reorder after %.*s: symbol not known"),
-                           "LC_COLLATE", arg->val.str.lenmb,
+                           "LC_COLLATE", (int) arg->val.str.lenmb,
                            arg->val.str.startmb);
                  collate->cursor = NULL;
                  no_error = 0;
@@ -2072,7 +2486,7 @@ error while adding equivalent collating symbol"));
                      process the whole rest of this reorder
                      specification.  */
                  lr_error (ldfile, _("%s: section `%.*s' not known"),
-                           "LC_COLLATE", arg->val.str.lenmb,
+                           "LC_COLLATE", (int) arg->val.str.lenmb,
                            arg->val.str.startmb);
 
                  do
@@ -2194,7 +2608,7 @@ error while adding equivalent collating symbol"));
              if (runp == NULL)
                {
                  lr_error (ldfile, _("%s: section `%.*s' not known"),
-                           "LC_COLLATE", arg->val.str.lenmb,
+                           "LC_COLLATE", (int) arg->val.str.lenmb,
                            arg->val.str.startmb);
                  lr_ignore_rest (ldfile, 0);
                }
index afad481f0a61a820aea9fba1be9b3542283ebb00..a56d7a7b8bb7d3f4870ad81a276802565a2a7642 100644 (file)
@@ -247,7 +247,7 @@ not correspond to a valid name in ISO 4217"),
        error (0, 0, _("%s: field `%s' not defined"),
               "LC_MONETARY", "mon_grouping");
 
-      monetary->mon_grouping = "\177";
+      monetary->mon_grouping = (char *) "\177";
       monetary->mon_grouping_len = 1;
     }
 
index 8f40520c6e88782513e1897f220f9adafd9609b7..1fdc94ff5bf3706b6ea870d705f2412840b0b458 100644 (file)
@@ -307,13 +307,6 @@ setlocale (int category, const char *locale)
       while (category-- > 0)
        if (category != LC_ALL)
          {
-           /* XXX hack.  Remove when collation works.  */
-           if (category == LC_COLLATE)
-             {
-               newdata[category] = NULL;
-               continue;
-             }
-
            newdata[category] = _nl_find_locale (locale_path, locale_path_len,
                                                 category,
                                                 &newnames[category]);
@@ -350,11 +343,6 @@ setlocale (int category, const char *locale)
 
       return composite;
     }
-  else if (category == LC_COLLATE)
-    {
-      /* XXX Remove when LC_COLLATE works.  */
-      return NULL;
-    }
   else
     {
       struct locale_data *newdata = NULL;
index b0d788645099afec881cd06e50c9d4900d37047b..0a30d2c25613f7d2370c23eb32bd11a7d3a70bb6 100644 (file)
@@ -1,3 +1,9 @@
+1999-12-23  Ulrich Drepper  <drepper@cygnus.com>
+
+       * locale/en_BW: New file.
+       * locale/en_ZW: New file.
+       Contributed by Schalk W. Cronjé <schalkc@ntaba.co.za>.
+
 1999-12-21  Ulrich Drepper  <drepper@cygnus.com>
 
        * locales/ja_JP: Fix cntrl mapping and era definition.
@@ -6,6 +12,7 @@
 1999-12-20  Ulrich Drepper  <drepper@cygnus.com>
 
        * locales/af_ZA: New file.
+       Contributed by Schalk W. Cronjé <schalkc@ntaba.co.za>.
 
 1999-12-19  Ulrich Drepper  <drepper@cygnus.com>