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>.
This commit is contained in:
Ulrich Drepper 1999-12-24 05:42:34 +00:00
parent 46fd4f671c
commit 575b273bdc
13 changed files with 488 additions and 171 deletions

View File

@ -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_

View 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))

View 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

View File

@ -20,11 +20,12 @@
#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 }
}
};

View 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)

View 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 */

View 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.

View File

@ -21,47 +21,22 @@
#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);
}

View 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 */

View 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)
{
/* 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;
}
if (runp->mbs != NULL)
{
struct element_t **eptr;
/* 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;
}
/* 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);
}

View 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;
}

View 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;

View 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>