- }
- }
-
- /* Reset counters for weights. */
- collate->weight_idx = 0;
- collate->nweight = 0;
- for (i = 0; i < collate->nrules; ++i)
- collate->weight_cnt[i] = 0;
- collate->current_patch = NULL;
-
- return result;
-}
-
-
-int
-collate_weight_bsymbol (struct linereader *ldfile, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
-{
- struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
- unsigned int here_weight;
- uint32_t value;
- void *tmp;
-
- assert (code->tok == tok_bsymbol);
-
- value = charset_find_value (&charset->char_table, code->val.str.start,
- code->val.str.len);
- if (value != ILLEGAL_CHAR_VALUE)
- {
- element_t *runp;
-
- if (find_entry (&collate->result, &value, sizeof (uint32_t),
- (void *)&runp) < 0)
- runp = NULL;
-
- while (runp != NULL
- && (runp->name[0] != value || runp->name[1] != L'\0'))
- runp = runp->next;
-
- here_weight = runp == NULL ? 0 : runp->this_weight;
- }
- else if (find_entry (&collate->elements, code->val.str.start,
- code->val.str.len, &tmp) >= 0)
- {
- element_t *runp = (element_t *) tmp;
-
- here_weight = runp->this_weight;
- }
- else if (find_entry (&collate->symbols, code->val.str.start,
- code->val.str.len, &tmp) >= 0)
- {
- here_weight = (unsigned int) tmp;
- }
- else
- {
- if (verbose)
- lr_error (ldfile, _("unknown symbol `%.*s': line ignored"),
- (int) code->val.str.len, code->val.str.start);
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
-
- /* When we currently work on a collation symbol we do not expect any
- weight. */
- if (collate->kind == symbol)
- {
- lr_error (ldfile, _("\
-specification of sorting weight for collation symbol does not make sense"));
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
-
- /* Add to the current collection of weights. */
- if (collate->nweight >= collate->nweight_max)
- {
- collate->nweight_max *= 2;
- collate->weight = (unsigned int *) xrealloc (collate->weight,
- collate->nweight_max);
- }
-
- /* If the weight is currently not known, we remember to patch the
- resulting tables. */
- if (here_weight == 0)
- {
- patch_t *newp;
-
- newp = (patch_t *) obstack_alloc (&collate->element_mem,
- sizeof (patch_t));
- newp->fname = ldfile->fname;
- newp->lineno = ldfile->lineno;
- newp->token = (const char *) obstack_copy0 (&collate->element_mem,
- code->val.str.start,
- code->val.str.len);
- newp->where.idx = collate->nweight++;
- newp->next = collate->current_patch;
- collate->current_patch = newp;
- }
- else
- collate->weight[collate->nweight++] = here_weight;
- ++collate->weight_cnt[collate->weight_idx];
-
- return 0;
-}
-
-
-int
-collate_next_weight (struct linereader *ldfile, struct localedef_t *locale)
-{
- struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
-
- if (collate->kind == symbol)
- {
- lr_error (ldfile, _("\
-specification of sorting weight for collation symbol does not make sense"));
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
-
- ++collate->weight_idx;
- if (collate->weight_idx >= collate->nrules)
- {
- lr_error (ldfile, _("too many weights"));
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
-
- return 0;
-}
-
-
-int
-collate_simple_weight (struct linereader *ldfile, struct localedef_t *locale,
- struct token *code, struct charset_t *charset)
-{
- struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
- unsigned int value = 0;
-
- /* There current tokens can be `IGNORE', `...', or a string. */
- switch (code->tok)
- {
- case tok_ignore:
- /* This token is allowed in all situations. */
- value = IGNORE_CHAR;
- break;
-
- case tok_ellipsis:
- /* The ellipsis is only allowed for the `...' or `UNDEFINED'
- entry. */
- if (collate->kind != ellipsis && collate->kind != undefined)
- {
- lr_error (ldfile, _("\
-`...' must only be used in `...' and `UNDEFINED' entries"));
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
- value = ELLIPSIS_CHAR;
- break;
-
- case tok_string:
- /* This can become difficult. We have to get the weights which
- correspond to the single wide chars in the string. But some
- of the `chars' might not be real characters, but collation
- elements or symbols. And so the string decoder might have
- signaled errors. The string at this point is not translated.
- I.e., all <...> sequences are still there. */
- {
- char *runp = code->val.str.start;
- void *tmp;
-
- while (*runp != '\0')
- {
- char *startp = (char *) runp;
- char *putp = (char *) runp;
- uint32_t wch;
-
- /* Lookup weight for char and store it. */
- if (*runp == '<')
- {
- while (*++runp != '\0' && *runp != '>')
- {
- if (*runp == ldfile->escape_char)
- if (*++runp == '\0')
- {
- lr_error (ldfile, _("unterminated weight name"));
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
- *putp++ = *runp;
- }
- if (*runp == '>')
- ++runp;
-
- if (putp == startp)
- {
- lr_error (ldfile, _("empty weight name: line ignored"));
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
-
- wch = charset_find_value (&charset->char_table, startp,
- putp - startp);
- if (wch != ILLEGAL_CHAR_VALUE)
- {
- element_t *pelem;
-
- if (find_entry (&collate->result, &wch, sizeof (uint32_t),
- (void *)&pelem) < 0)
- pelem = NULL;
-
- while (pelem != NULL
- && (pelem->name[0] != wch
- || pelem->name[1] != L'\0'))
- pelem = pelem->next;
-
- value = pelem == NULL ? 0 : pelem->this_weight;
- }
- else if (find_entry (&collate->elements, startp, putp - startp,
- &tmp) >= 0)
- {
- element_t *pelem = (element_t *) tmp;
-
- value = pelem->this_weight;
- }
- else if (find_entry (&collate->symbols, startp, putp - startp,
- &tmp) >= 0)
- {
- value = (unsigned int) tmp;
- }
- else
- {
- if (verbose)
- lr_error (ldfile, _("unknown symbol `%.*s': line ignored"),
- (int) (putp - startp), startp);
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
- }
- else
- {
- element_t *wp;
- uint32_t wch;
-
- if (*runp == ldfile->escape_char)
- {
- static const char digits[] = "0123456789abcdef";
- const char *dp;
- int base;
-
- ++runp;
- if (tolower (*runp) == 'x')
- {
- ++runp;
- base = 16;
- }
- else if (tolower (*runp) == 'd')
- {
- ++runp;
- base = 10;
- }
- else
- base = 8;
-
- dp = strchr (digits, tolower (*runp));
- if (dp == NULL || (dp - digits) >= base)
- {
- illegal_char:
- lr_error (ldfile, _("\
-illegal character constant in string"));
- lr_ignore_rest (ldfile, 0);
- return -1;
- }
- wch = dp - digits;
- ++runp;
-
- dp = strchr (digits, tolower (*runp));
- if (dp == NULL || (dp - digits) >= base)
- goto illegal_char;
- wch *= base;
- wch += dp - digits;
- ++runp;
-
- if (base != 16)
- {
- dp = strchr (digits, tolower (*runp));
- if (dp != NULL && (dp - digits < base))
- {
- wch *= base;
- wch += dp - digits;
- ++runp;
- }
- }
- }
- else
- wch = (uint32_t) *runp++;
-
- /* Lookup the weight for WCH. */
- if (find_entry (&collate->result, &wch, sizeof (wch),
- (void *)&wp) < 0)
- wp = NULL;
-
- while (wp != NULL
- && (wp->name[0] != wch || wp->name[1] != L'\0'))
- wp = wp->next;
-
- value = wp == NULL ? 0 : wp->this_weight;
-
- /* To get the correct name for the error message. */
- putp = runp;