diff options
author | Roland McGrath <roland@gnu.org> | 1996-07-29 03:49:00 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1996-07-29 03:49:00 +0000 |
commit | ce7a5ef4bc04ee3ca9d2f42377ca6593d8492a52 (patch) | |
tree | efbd26a9837de025fc405475655d24d83761cfee /locale/programs | |
parent | cddcfecfd1a8f91ee1da1c0147a4f07aee1846a0 (diff) | |
download | glibc-ce7a5ef4bc04ee3ca9d2f42377ca6593d8492a52.tar glibc-ce7a5ef4bc04ee3ca9d2f42377ca6593d8492a52.tar.gz glibc-ce7a5ef4bc04ee3ca9d2f42377ca6593d8492a52.tar.bz2 glibc-ce7a5ef4bc04ee3ca9d2f42377ca6593d8492a52.zip |
Sun Jul 28 23:46:14 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* time/strftime.c (strftime: do_number): Initialize PRINTED to
MAXDIGITS in case P is null and so sprintf is never actually called.
Mon Jul 29 02:46:23 1996 Ulrich Drepper <drepper@cygnus.com>
Add support for the to-be-written internationalized regexp.
This code must be able to use collation symbols and collation
equivalent classes.
* locale/C-collate.c (_nl_C_LC_COLLATE_symbol_hash,
_nl_C_LC_COLLATE_symbol_strings, _nl_C_LC_COLLATE_symbol_classes):
New global variables for collation classes.
* locale/categories.def: Add new descriptions for collation symbols
and collation classes.
* locale/langinfo.h: Add constants for collation symbols and
collation classes.
* locale/lc-collate.c: Add new global variables for collation symbols
and collation classes.
(_nl_postload_collate): Initialize new variables.
* locale/programs/ld-collate.c: Add code to emit tables for
collation symbols and collation classes.
* locale/programs/locales.h: Change prototype for `collate_output'.
* locale/programs/locfile.c (write_all_categories): Call
`collate_output' with new argument.
* locale/localeinfo.h: Add declaration for new global vars.
(union locale_data_value): New member wstr for `wchar_t' strings.
* locale/programs/locale-spec.c: Handle `collate-classes'
keyword and print information about available collation classes.
* locale/strlen-hash.h: New file. Simple hashing function which
takes a string with known length.
* locale/Makefile (distribute): Add strlen-hash.h.
(locale-modules): New var. Additional files for `locale' program.
* locale/C-ctype.c: Rewrite to avoid using string for giving values
which are of type `u_int32_t'.
Correct entry for EOF in toupper and tolower tables.
* locale/loadlocale.c (_nl_load_locale): Add cast to prevent
warning.
* locale/programs/ld-ctype.c (ctype_output): Add code to make
sure that all tables in binary file are words aligned.
* locale/programs/locfile.c (write_locale_data): Correct handling
of LC_MESSAGES locale. Create directory if necessary.
* locale/setlocale.c (setlocale): Add cast to avoid warning.
* string/string.h: Add prototype for `__strndup'.
Wed Jul 24 19:10:00 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
* wcsmbs/mbrtowc.c: Remove unused variable.
Sun Jul 28 22:40:25 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* sysdeps/unix/sysv/linux/configure.in (LIBC_LINUX_VERSION): Update to
2.0.10; some problems were reported with an earlier version, and this
one is known to work.
* sysdeps/generic/dl-sysdep.c (__libc_enable_secure): New variable.
* sysdeps/mach/hurd/dl-sysdep.c: Likewise.
Diffstat (limited to 'locale/programs')
-rw-r--r-- | locale/programs/ld-collate.c | 402 | ||||
-rw-r--r-- | locale/programs/ld-ctype.c | 33 | ||||
-rw-r--r-- | locale/programs/locale-spec.c | 33 | ||||
-rw-r--r-- | locale/programs/locales.h | 3 | ||||
-rw-r--r-- | locale/programs/locfile.c | 33 |
5 files changed, 476 insertions, 28 deletions
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c index 4bdf0b2256..77e946535d 100644 --- a/locale/programs/ld-collate.c +++ b/locale/programs/ld-collate.c @@ -1,6 +1,6 @@ /* Copyright (C) 1995, 1996 Free Software Foundation, Inc. This file is part of the GNU C Library. -Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>. +Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as @@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */ #include "locales.h" #include "simple-hash.h" #include "stringtrans.h" +#include "strlen-hash.h" /* Uncomment the following line in the production version. */ /* #define NDEBUG 1 */ @@ -83,7 +84,7 @@ typedef struct element_t } element_t; -/* The real definition of the struct for the LC_CTYPE locale. */ +/* The real definition of the struct for the LC_COLLATE locale. */ struct locale_collate_t { /* Collate symbol table. Simple mapping to number. */ @@ -275,15 +276,13 @@ collate_finish (struct localedef_t *locale, struct charset_t *charset) collate->undefined_len = 2; /* For the name: 1 x wchar_t + L'\0'. */ for (cnt = 0; cnt < collate->nrules; ++cnt) collate->undefined_len += 1 + collate->undefined.ordering[cnt]; - - /* Collating symbols are not used anymore. */ - (void) delete_hash (&collate->symbols); } void -collate_output (struct localedef_t *locale, const char *output_path) +collate_output (struct localedef_t *locale, struct charset_t *charset, + const char *output_path) { struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate; u_int32_t table_size, table_best, level_best, sum_best; @@ -296,10 +295,29 @@ collate_output (struct localedef_t *locale, const char *output_path) struct locale_file data; u_int32_t idx[nelems]; struct obstack non_simple; + struct obstack string_pool; size_t cnt, entry_size; u_int32_t undefined_offset = UINT_MAX; u_int32_t *table, *extra, *table2, *extra2; size_t extra_len; + u_int32_t element_hash_tab_size; + u_int32_t *element_hash_tab; + u_int32_t *element_hash_tab_ob; + u_int32_t element_string_pool_size; + char *element_string_pool; + u_int32_t element_value_size; + wchar_t *element_value; + wchar_t *element_value_ob; + u_int32_t symbols_hash_tab_size; + u_int32_t *symbols_hash_tab; + u_int32_t *symbols_hash_tab_ob; + u_int32_t symbols_string_pool_size; + char *symbols_string_pool; + u_int32_t symbols_class_size; + u_int32_t *symbols_class; + u_int32_t *symbols_class_ob; + hash_table *hash_tab; + unsigned int dummy_weights[collate->nrules + 1]; sum_best = UINT_MAX; table_best = 0xffff; @@ -342,6 +360,7 @@ Computing table size for collation information might take a while..."), fputs (_(" done\n"), stderr); obstack_init (&non_simple); + obstack_init (&string_pool); data.magic = LIMAGIC (LC_COLLATE); data.n = nelems; @@ -608,6 +627,258 @@ Computing table size for collation information might take a while..."), for (cnt = 0; cnt < extra_len / sizeof (u_int32_t); ++cnt) extra2[cnt] = SWAPU32 (extra2[cnt]); + /* We need a simple hashing table to get a collation-element->chars + mapping. We again use internal hasing using a secondary hashing + function. + + Each string has an associate hashing value V, computed by a + fixed function. To locate the string we use open addressing with + double hashing. The first index will be V % M, where M is the + size of the hashing table. If no entry is found, iterating with + a second, independent hashing function takes place. This second + value will be 1 + V % (M - 2). The approximate number of probes + will be + + for unsuccessful search: (1 - N / M) ^ -1 + for successful search: - (N / M) ^ -1 * ln (1 - N / M) + + where N is the number of keys. + + If we now choose M to be the next prime bigger than 4 / 3 * N, + we get the values 4 and 1.85 resp. Because unsuccesful searches + are unlikely this is a good value. Formulas: [Knuth, The Art of + Computer Programming, Volume 3, Sorting and Searching, 1973, + Addison Wesley] */ + if (collate->elements.filled == 0) + { + /* We don't need any element table since there are no collating + elements. */ + element_hash_tab_size = 0; + element_hash_tab = NULL; + element_hash_tab_ob = NULL; + element_string_pool_size = 0; + element_string_pool = NULL; + element_value_size = 0; + element_value = NULL; + element_value_ob = NULL; + } + else + { + void *ptr; /* Running pointer. */ + const char *key; /* Key for current bucket. */ + size_t keylen; /* Length of key data. */ + const element_t *data; /* Data, i.e., the character sequence. */ + + element_hash_tab_size = next_prime ((collate->elements.filled * 4) / 3); + if (element_hash_tab_size < 7) + /* We need a minimum to make the following code work. */ + element_hash_tab_size = 7; + + element_hash_tab = obstack_alloc (&non_simple, (2 * element_hash_tab_size + * sizeof (u_int32_t))); + memset (element_hash_tab, '\377', (2 * element_hash_tab_size + * sizeof (u_int32_t))); + + ptr = NULL; + while (iterate_table (&collate->elements, &ptr, (const void **) &key, + &keylen, (void **) &data) == 0) + { + size_t hash_val = hash_string (key, keylen); + size_t idx = hash_val % element_hash_tab_size; + + if (element_hash_tab[2 * idx] != (~((u_int32_t) 0))) + { + /* We need the second hashing function. */ + size_t c = 1 + (hash_val % (element_hash_tab_size - 2)); + + do + if (idx >= element_hash_tab_size - c) + idx -= element_hash_tab_size - c; + else + idx += c; + while (element_hash_tab[2 * idx] != (~((u_int32_t) 0))); + } + + element_hash_tab[2 * idx] = obstack_object_size (&non_simple); + element_hash_tab[2 * idx + 1] = (obstack_object_size (&string_pool) + / sizeof (wchar_t)); + + obstack_grow0 (&non_simple, key, keylen); + obstack_grow (&string_pool, data->name, + (wcslen (data->name) + 1) * sizeof (wchar_t)); + } + + if (obstack_object_size (&non_simple) % 4 != 0) + obstack_blank (&non_simple, + 4 - (obstack_object_size (&non_simple) % 4)); + element_string_pool_size = obstack_object_size (&non_simple); + element_string_pool = obstack_finish (&non_simple); + + element_value_size = obstack_object_size (&string_pool); + element_value = obstack_finish (&string_pool); + + /* Create the tables for the other byte order. */ + element_hash_tab_ob = obstack_alloc (&non_simple, + (2 * element_hash_tab_size + * sizeof (u_int32_t))); + for (cnt = 0; cnt < 2 * element_hash_tab_size; ++cnt) + element_hash_tab_ob[cnt] = SWAPU32 (element_hash_tab[cnt]); + + element_value_ob = obstack_alloc (&string_pool, element_value_size); + if (sizeof (wchar_t) != 4) + { + fputs ("sizeof (wchar_t) != 4 currently not handled", stderr); + abort (); + } + for (cnt = 0; cnt < element_value_size / 4; ++cnt) + element_value_ob[cnt] = SWAPU32 (element_value[cnt]); + } + + /* Store collation elements as map to collation class. There are + three kinds of symbols: + - simple characters + - collation elements + - collation symbols + We need to make a table which lets the user to access the primary + weight based on the symbol string. */ + symbols_hash_tab_size = next_prime ((4 * (charset->char_table.filled + + collate->elements.filled + + collate->symbols.filled)) / 3); + symbols_hash_tab = obstack_alloc (&non_simple, (2 * symbols_hash_tab_size + * sizeof (u_int32_t))); + memset (symbols_hash_tab, '\377', (2 * symbols_hash_tab_size + * sizeof (u_int32_t))); + + /* Now fill the array. First the symbols from the character set, + then the collation elements and last the collation symbols. */ + hash_tab = &charset->char_table; + while (1) + { + void *ptr; /* Running pointer. */ + const char *key; /* Key for current bucket. */ + size_t keylen; /* Length of key data. */ + void *data; /* Data. */ + + ptr = NULL; + while (iterate_table (hash_tab, &ptr, (const void **) &key, + &keylen, (void **) &data) == 0) + { + size_t hash_val; + size_t idx; + u_int32_t word; + unsigned int *weights; + + if (hash_tab == &charset->char_table + || hash_tab == &collate->elements) + { + element_t *lastp, *firstp; + wchar_t dummy_name[2]; + const wchar_t *name; + size_t name_len; + + if (hash_tab == &charset->char_table) + { + dummy_name[0] = (wchar_t) ((unsigned long int) data); + dummy_name[1] = L'\0'; + name = dummy_name; + name_len = sizeof (wchar_t); + } + else + { + element_t *elemp = (element_t *) data; + name = elemp->name; + name_len = wcslen (name) * sizeof (wchar_t); + } + + /* First check whether this character is used at all. */ + if (find_entry (&collate->result, name, name_len, + (void *) &firstp) < 0) + /* The symbol is not directly mentioned in the collation. + I.e., we use the value for UNDEFINED. */ + lastp = &collate->undefined; + else + { + /* The entry for the simple character is always found at + the end. */ + lastp = firstp; + while (lastp->next != NULL && wcscmp (name, lastp->name)) + lastp = lastp->next; + } + + weights = lastp->ordering; + } + else + { + dummy_weights[0] = 1; + dummy_weights[collate->nrules] + = (unsigned int) ((unsigned long int) data); + + weights = dummy_weights; + } + + /* In LASTP->ordering we now have the collation class. + Determine the place in the hashing table next. */ + hash_val = hash_string (key, keylen); + idx = hash_val % symbols_hash_tab_size; + + if (symbols_hash_tab[2 * idx] != (~((u_int32_t) 0))) + { + /* We need the second hashing function. */ + size_t c = 1 + (hash_val % (symbols_hash_tab_size - 2)); + + do + if (idx >= symbols_hash_tab_size - c) + idx -= symbols_hash_tab_size - c; + else + idx += c; + while (symbols_hash_tab[2 * idx] != (~((u_int32_t) 0))); + } + + symbols_hash_tab[2 * idx] = obstack_object_size (&string_pool); + symbols_hash_tab[2 * idx + 1] = (obstack_object_size (&non_simple) + / sizeof (u_int32_t)); + + obstack_grow0 (&string_pool, key, keylen); + /* Adding the first weight looks complicated. We have to deal + with the kind it is stored and with the fact that original + form uses `unsigned int's while we need `u_int32_t' here. */ + word = weights[0]; + obstack_grow (&non_simple, &word, sizeof (u_int32_t)); + for (cnt = 0; cnt < weights[0]; ++cnt) + { + word = weights[collate->nrules + cnt]; + obstack_grow (&non_simple, &word, sizeof (u_int32_t)); + } + } + + if (hash_tab == &charset->char_table) + hash_tab = &collate->elements; + else if (hash_tab == &collate->elements) + hash_tab = &collate->symbols; + else + break; + } + + /* Now we have the complete tables. */ + if (obstack_object_size (&string_pool) % 4 != 0) + obstack_blank (&non_simple, 4 - (obstack_object_size (&string_pool) % 4)); + symbols_string_pool_size = obstack_object_size (&string_pool); + symbols_string_pool = obstack_finish (&string_pool); + + symbols_class_size = obstack_object_size (&non_simple); + symbols_class = obstack_finish (&non_simple); + + /* Generate tables with other byte order. */ + symbols_hash_tab_ob = obstack_alloc (&non_simple, (2 * symbols_hash_tab_size + * sizeof (u_int32_t))); + for (cnt = 0; cnt < 2 * symbols_hash_tab_size; ++cnt) + symbols_hash_tab_ob[cnt] = SWAPU32 (symbols_hash_tab[cnt]); + + symbols_class_ob = obstack_alloc (&non_simple, symbols_class_size); + for (cnt = 0; cnt < symbols_class_size / 4; ++cnt) + symbols_class_ob[cnt] = SWAPU32 (symbols_class[cnt]); + + /* Store table adresses and lengths. */ #if __BYTE_ORDER == __BIG_ENDIAN iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_TABLE_EB)].iov_base = table; @@ -642,12 +913,124 @@ Computing table size for collation information might take a while..."), iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_base = &undefined_offset; iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_UNDEFINED)].iov_len = sizeof (u_int32_t); + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_SIZE)].iov_base + = &element_hash_tab_size; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_SIZE)].iov_len + = sizeof (u_int32_t); + +#if __BYTE_ORDER == __BIG_ENDIAN + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_base + = element_hash_tab; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_len + = 2 * element_hash_tab_size * sizeof (u_int32_t); + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_base + = element_hash_tab_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_len + = 2 * element_hash_tab_size * sizeof (u_int32_t); +#else + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_base + = element_hash_tab; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EL)].iov_len + = 2 * element_hash_tab_size * sizeof (u_int32_t); + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_base + = element_hash_tab_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_HASH_EB)].iov_len + = 2 * element_hash_tab_size * sizeof (u_int32_t); +#endif + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_STR_POOL)].iov_base + = element_string_pool; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_STR_POOL)].iov_len + = element_string_pool_size; + +#if __BYTE_ORDER == __BIG_ENDIAN + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EB)].iov_base + = element_value; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EB)].iov_len + = element_value_size; + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EL)].iov_base + = element_value_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EL)].iov_len + = element_value_size; +#else + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EL)].iov_base + = element_value; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EL)].iov_len + = element_value_size; + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EB)].iov_base + = element_value_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_VAL_EB)].iov_len + = element_value_size; +#endif + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZE)].iov_base + = &symbols_hash_tab_size; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZE)].iov_len + = sizeof (u_int32_t); + +#if __BYTE_ORDER == __BIG_ENDIAN + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_base + = symbols_hash_tab; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_len + = 2 * symbols_hash_tab_size * sizeof (u_int32_t); + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_base + = symbols_hash_tab_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_len + = 2 * symbols_hash_tab_size * sizeof (u_int32_t); +#else + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_base + = symbols_hash_tab; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EL)].iov_len + = 2 * symbols_hash_tab_size * sizeof (u_int32_t); + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_base + = symbols_hash_tab_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_EB)].iov_len + = 2 * symbols_hash_tab_size * sizeof (u_int32_t); +#endif + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_STR_POOL)].iov_base + = symbols_string_pool; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_STR_POOL)].iov_len + = symbols_string_pool_size; + +#if __BYTE_ORDER == __BIG_ENDIAN + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_CLASS_EB)].iov_base + = symbols_class; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_ELEM_CLASS_EB)].iov_len + = symbols_class_size; + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_CLASS_EL)].iov_base + = symbols_class_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_CLASS_EL)].iov_len + = symbols_class_size; +#else + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_CLASS_EL)].iov_base + = symbols_class; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_CLASS_EL)].iov_len + = symbols_class_size; + + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_CLASS_EB)].iov_base + = symbols_class_ob; + iov[2 + _NL_ITEM_INDEX (_NL_COLLATE_SYMB_CLASS_EB)].iov_len + = symbols_class_size; +#endif + /* Update idx array. */ idx[0] = iov[0].iov_len + iov[1].iov_len; for (cnt = 1; cnt < nelems; ++cnt) idx[cnt] = idx[cnt - 1] + iov[1 + cnt].iov_len; write_locale_data (output_path, "LC_COLLATE", 2 + nelems, iov); + + obstack_free (&non_simple, NULL); + obstack_free (&string_pool, NULL); } @@ -729,7 +1112,7 @@ collate_element_from (struct linereader *lr, struct localedef_t *locale, if (elemp->name[0] == L'\0' || elemp->name[1] == L'\0') { - lr_error (lr, _("illegal colltion element")); + lr_error (lr, _("illegal collation element")); return; } @@ -762,8 +1145,7 @@ collate_element_from (struct linereader *lr, struct localedef_t *locale, { if (set_entry (&collate->result, elemp->name, sizeof (wchar_t), elemp) < 0) - error (EXIT_FAILURE, 0, - _("\ + error (EXIT_FAILURE, 0, _("\ error while inserting collation element into hash table")); } else @@ -1019,7 +1401,7 @@ line before ellipsis does not contain definition for character constant")); } /* Now it's time to handle the ellipsis in the previous line. We do - this only when the last line contained an definition for an + this only when the last line contained an definition for a character, the current line also defines an character, the character code for the later is bigger than the former. */ if (collate->was_ellipsis) diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c index 0ca3af584b..196f990745 100644 --- a/locale/programs/ld-ctype.c +++ b/locale/programs/ld-ctype.c @@ -387,8 +387,8 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, { #define CTYPE_DATA(name, base, len) \ case _NL_ITEM_INDEX (name): \ - iov[2 + elem + offset].iov_base = base; \ - iov[2 + elem + offset].iov_len = len; \ + iov[2 + elem + offset].iov_base = (base); \ + iov[2 + elem + offset].iov_len = (len); \ if (elem + 1 < nelems) \ idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len; \ break @@ -443,9 +443,9 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, = strlen (ctype->classnames[cnt]) + 1; total += iov[2 + elem + offset].iov_len; } - iov[2 + elem + offset].iov_base = (void *) ""; - iov[2 + elem + offset].iov_len = 1; - ++total; + iov[2 + elem + offset].iov_base = (void *) "\0\0\0"; + iov[2 + elem + offset].iov_len = 1 + (4 - ((total + 1) % 4)); + total += 1 + (4 - ((total + 1) % 4)); if (elem + 1 < nelems) idx[elem + 1] = idx[elem] + total; @@ -462,9 +462,9 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, = strlen (ctype->mapnames[cnt]) + 1; total += iov[2 + elem + offset].iov_len; } - iov[2 + elem + offset].iov_base = (void *) ""; - iov[2 + elem + offset].iov_len = 1; - ++total; + iov[2 + elem + offset].iov_base = (void *) "\0\0\0"; + iov[2 + elem + offset].iov_len = 1 + (4 - ((total + 1) % 4)); + total += 1 + (4 - ((total + 1) % 4)); if (elem + 1 < nelems) idx[elem + 1] = idx[elem] + total; @@ -476,8 +476,21 @@ ctype_output (struct localedef_t *locale, struct charset_t *charset, CTYPE_DATA (_NL_CTYPE_MB_CUR_MAX, &ctype->mb_cur_max, sizeof (u_int32_t)); - CTYPE_DATA (_NL_CTYPE_CODESET_NAME, - ctype->codeset_name, strlen (ctype->codeset_name) + 1); + case _NL_ITEM_INDEX (_NL_CTYPE_CODESET_NAME): + total = strlen (ctype->codeset_name) + 1; + if (total % 4 == 0) + iov[2 + elem + offset].iov_base = (char *) ctype->codeset_name; + else + { + iov[2 + elem + offset].iov_base = alloca ((total + 3) & ~3); + memcpy (iov[2 + elem + offset].iov_base, ctype->codeset_name, + total); + total = (total + 3) & ~3; + } + iov[2 + elem + offset].iov_len = total; + if (elem + 1 < nelems) + idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len; + break; default: assert (! "unknown CTYPE element"); diff --git a/locale/programs/locale-spec.c b/locale/programs/locale-spec.c index e408421656..c595524bbb 100644 --- a/locale/programs/locale-spec.c +++ b/locale/programs/locale-spec.c @@ -92,4 +92,37 @@ locale_special (const char *name, int show_category_name, putchar ('\n'); return; } + + if (strcmp (name, "collate-classes") == 0) + { + size_t nelem = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZE); + size_t cnt; + int first = 1; + + if (show_category_name) + puts ("LC_COLLATE"); + if (show_keyword_name) + fputs ("collate-classes=", stdout); + + for (cnt = 0; cnt < nelem; ++cnt) + if (__collate_symbol_hash[2 * cnt] != 0xffffffff) + { + printf ("%s<%s>", first ? "" : ",", + &__collate_symbol_strings[__collate_symbol_hash[2 * cnt]]); +#if 1 + { + size_t idx = __collate_symbol_hash[2 * cnt + 1]; + size_t cls; + + putchar ('='); + for (cls = 0; cls < __collate_symbol_classes[idx]; ++cls) + printf ("%s%d", cls == 0 ? "" : ":", + __collate_symbol_classes[idx + 1 + cls]); + } +#endif + first = 0; + } + putchar ('\n'); + return; + } } diff --git a/locale/programs/locales.h b/locale/programs/locales.h index 9fe85e9e07..95e166e3ef 100644 --- a/locale/programs/locales.h +++ b/locale/programs/locales.h @@ -122,7 +122,8 @@ void collate_startup (struct linereader *lr, struct localedef_t *locale, void collate_finish (struct localedef_t *locale, struct charset_t *charset); -void collate_output (struct localedef_t *locale, const char *output_path); +void collate_output (struct localedef_t *locale, struct charset_t *charset, + const char *output_path); void collate_element_to (struct linereader *lr, struct localedef_t *locale, struct token *code, struct charset_t *charset); diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c index 436df2e976..63ebc4b856 100644 --- a/locale/programs/locfile.c +++ b/locale/programs/locfile.c @@ -919,7 +919,7 @@ write_all_categories (struct localedef_t *locale, struct charset_t *charset, { /* Call all functions to write locale data. */ ctype_output (locale, charset, output_path); - collate_output (locale, output_path); + collate_output (locale, charset, output_path); monetary_output (locale, output_path); numeric_output (locale, output_path); time_output (locale, output_path); @@ -943,13 +943,31 @@ write_locale_data (const char *output_path, const char *category, But for LC_MESSAGES we have to take care for the translation data. This means we need to have a directory LC_MESSAGES in which we place the file under the name SYS_LC_MESSAGES. */ + sprintf (fname, "%s%s", output_path, category); if (strcmp (category, "LC_MESSAGES") == 0) - fd = -1; - else { - sprintf (fname, "%s%s", output_path, category); - fd = creat (fname, 0666); + struct stat st; + + if (stat (fname, &st) < 0) + { + if (mkdir (fname, 0777) < 0) + fd = creat (fname, 0666); + else + { + fd = -1; + errno = EISDIR; + } + } + else if (S_ISREG (st.st_mode)) + fd = creat (fname, 0666); + else + { + fd = -1; + errno = EISDIR; + } } + else + fd = creat (fname, 0666); if (fd == -1) { @@ -965,8 +983,9 @@ write_locale_data (const char *output_path, const char *category, if (fd == -1) { - error (0, save_err, _("cannot open output file for category `%s'"), - category); + error (0, save_err, _("\ +cannot open output file `%s' for category `%s'"), + fname, category); return; } } |