aboutsummaryrefslogtreecommitdiff
path: root/locale/programs
diff options
context:
space:
mode:
Diffstat (limited to 'locale/programs')
-rw-r--r--locale/programs/ld-ctype.c162
1 files changed, 104 insertions, 58 deletions
diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
index 4f5653af23..f624769b68 100644
--- a/locale/programs/ld-ctype.c
+++ b/locale/programs/ld-ctype.c
@@ -106,6 +106,16 @@ struct translit_ignore_t
};
+/* Type to describe a transliteration include statement. */
+struct translit_include_t
+{
+ const char *copy_locale;
+ const char *copy_repertoire;
+
+ struct translit_include_t *next;
+};
+
+
/* The real definition of the struct for the LC_CTYPE locale. */
struct locale_ctype_t
{
@@ -155,8 +165,7 @@ struct locale_ctype_t
uint32_t map_offset;
/* Transliteration information. */
- const char *translit_copy_locale;
- const char *translit_copy_repertoire;
+ struct translit_include_t *translit_include;
struct translit_t *translit;
struct translit_ignore_t *translit_ignore;
uint32_t ntranslit_ignore;
@@ -2609,11 +2618,22 @@ with character code range values one must use the absolute ellipsis `...'"));
break;
case tok_translit_start:
- /* Ignore the rest of the line if we don't need the input of
- this line. */
+ /* Ignore the entire translit section with its peculiar syntax
+ if we don't need the input. */
if (ignore_content)
{
- lr_ignore_rest (ldfile, 0);
+ do
+ {
+ lr_ignore_rest (ldfile, 0);
+ now = lr_token (ldfile, charmap, NULL);
+ }
+ while (now->tok != tok_translit_end && now->tok != tok_eof);
+
+ if (now->tok == tok_eof)
+ lr_error (ldfile, _(\
+"%s: `translit_start' section does not end with `translit_end'"),
+ "LC_CTYPE");
+
break;
}
@@ -2635,17 +2655,12 @@ with character code range values one must use the absolute ellipsis `...'"));
/* Ignore empty lines. */
continue;
- if (now->tok == tok_translit_end)
- {
- lr_ignore_rest (ldfile, 0);
- break;
- }
-
if (now->tok == tok_include)
{
/* We have to include locale. */
const char *locale_name;
const char *repertoire_name;
+ struct translit_include_t *include_stmt, **include_ptr;
now = lr_token (ldfile, charmap, NULL);
/* This should be a string or an identifier. In any
@@ -2671,24 +2686,24 @@ with character code range values one must use the absolute ellipsis `...'"));
goto translit_syntax;
repertoire_name = now->val.str.startmb;
- /* We must not have more than one `include'. */
- if (ctype->translit_copy_locale != NULL)
- {
- lr_error (ldfile, _("\
-%s: only one `include' instruction allowed"), "LC_CTYPE");
- lr_ignore_rest (ldfile, 0);
- continue;
- }
+ /* Save the include statement for later processing. */
+ include_stmt = (struct translit_include_t *)
+ xmalloc (sizeof (struct translit_include_t));
+ include_stmt->copy_locale = locale_name;
+ include_stmt->copy_repertoire = repertoire_name;
+ include_stmt->next = NULL;
- ctype->translit_copy_locale = locale_name;
- ctype->translit_copy_repertoire = repertoire_name;
+ include_ptr = &ctype->translit_include;
+ while (*include_ptr != NULL)
+ include_ptr = &(*include_ptr)->next;
+ *include_ptr = include_stmt;
/* The rest of the line must be empty. */
lr_ignore_rest (ldfile, 1);
/* Make sure the locale is read. */
- add_to_readlist (LC_CTYPE, ctype->translit_copy_locale,
- repertoire_name, 1, NULL);
+ add_to_readlist (LC_CTYPE, locale_name, repertoire_name,
+ 1, NULL);
continue;
}
else if (now->tok == tok_default_missing)
@@ -2753,6 +2768,12 @@ previous definition was here"));
read_translit_entry (ldfile, ctype, now, charmap, repertoire);
}
ldfile->return_widestr = 0;
+
+ if (now->tok == tok_eof)
+ lr_error (ldfile, _(\
+"%s: `translit_start' section does not end with `translit_end'"),
+ "LC_CTYPE");
+
break;
case tok_ident:
@@ -3591,6 +3612,62 @@ wctrans_table_add (struct wctrans_table *t, uint32_t wc, uint32_t mapped_wc)
}
+/* Flattens the included transliterations into a translit list.
+ Inserts them in the list at `cursor', and returns the new cursor. */
+static struct translit_t **
+translit_flatten (struct locale_ctype_t *ctype, struct charmap_t *charmap,
+ struct translit_t **cursor)
+{
+ while (ctype->translit_include != NULL)
+ {
+ const char *copy_locale = ctype->translit_include->copy_locale;
+ const char *copy_repertoire = ctype->translit_include->copy_repertoire;
+ struct localedef_t *other;
+
+ /* Unchain the include statement. During the depth-first traversal
+ we don't want to visit any locale more than once. */
+ ctype->translit_include = ctype->translit_include->next;
+
+ other = find_locale (LC_CTYPE, copy_locale, copy_repertoire, charmap);
+
+ if (other == NULL)
+ {
+ error (0, 0, _("\
+%s: transliteration data from locale `%s' not available"),
+ "LC_CTYPE", copy_locale);
+ }
+ else
+ {
+ struct locale_ctype_t *other_ctype =
+ other->categories[LC_CTYPE].ctype;
+
+ cursor = translit_flatten (other_ctype, charmap, cursor);
+ assert (other_ctype->translit_include == NULL);
+
+ if (other_ctype->translit != NULL)
+ {
+ /* Insert the other_ctype->translit list at *cursor. */
+ struct translit_t *endp = other_ctype->translit;
+ while (endp->next != NULL)
+ endp = endp->next;
+
+ endp->next = *cursor;
+ *cursor = other_ctype->translit;
+
+ /* Avoid any risk of circular lists. */
+ other_ctype->translit = NULL;
+
+ cursor = &endp->next;
+ }
+
+ if (ctype->default_missing == NULL)
+ ctype->default_missing = other_ctype->default_missing;
+ }
+ }
+
+ return cursor;
+}
+
static void
allocate_arrays (struct locale_ctype_t *ctype, struct charmap_t *charmap,
struct repertoire_t *repertoire)
@@ -3867,41 +3944,10 @@ allocate_arrays (struct locale_ctype_t *ctype, struct charmap_t *charmap,
complicated algorithm which uses a hash table to locate the entries.
For now I'll use a simple array which can be searching using binary
search. */
- if (ctype->translit_copy_locale != NULL)
- {
- /* Fold in the transliteration information from the locale mentioned
- in the `include' statement. */
- struct locale_ctype_t *here = ctype;
-
- do
- {
- struct localedef_t *other = find_locale (LC_CTYPE,
- here->translit_copy_locale,
- repertoire->name, charmap);
-
- if (other == NULL)
- {
- error (0, 0, _("\
-%s: transliteration data from locale `%s' not available"),
- "LC_CTYPE", here->translit_copy_locale);
- break;
- }
-
- here = other->categories[LC_CTYPE].ctype;
-
- /* Enqueue the information if necessary. */
- if (here->translit != NULL)
- {
- struct translit_t *endp = here->translit;
- while (endp->next != NULL)
- endp = endp->next;
-
- endp->next = ctype->translit;
- ctype->translit = here->translit;
- }
- }
- while (here->translit_copy_locale != NULL);
- }
+ if (ctype->translit_include != NULL)
+ /* Traverse the locales mentioned in the `include' statements in a
+ depth-first way and fold in their transliteration information. */
+ translit_flatten (ctype, charmap, &ctype->translit);
if (ctype->translit != NULL)
{