diff options
Diffstat (limited to 'iconv/gconv_db.c')
-rw-r--r-- | iconv/gconv_db.c | 271 |
1 files changed, 78 insertions, 193 deletions
diff --git a/iconv/gconv_db.c b/iconv/gconv_db.c index 2e951294e4..4aac076538 100644 --- a/iconv/gconv_db.c +++ b/iconv/gconv_db.c @@ -375,221 +375,111 @@ find_derivation (const char *toset, const char *toset_expand, while (node != NULL) { - int cmpres = strncmp (current->result_set, node->from_constpfx, - MIN (current->result_set_len, - node->from_constpfx_len)); - + int cmpres = strcmp (current->result_set, node->from_string); if (cmpres == 0) { /* Walk through the list of modules with this prefix and try to match the name. */ struct gconv_module *runp; - if (current->result_set_len < node->from_constpfx_len) - /* Cannot possibly match. */ - break; - /* Check all the modules with this prefix. */ runp = node; do { - const char *result_set = NULL; - - if (runp->from_pattern == NULL) - { - /* This is a simple entry and therefore we have a - found an matching entry if the strings are really - equal. */ - if (current->result_set_len == runp->from_constpfx_len) - { - if (strcmp (runp->to_string, "-") == 0) - result_set = toset_expand ?: toset; - else - result_set = runp->to_string; - } - } - else + const char *result_set = (strcmp (runp->to_string, "-") == 0 + ? (toset_expand ?: toset) + : runp->to_string); + int cost_hi = runp->cost_hi + current->cost_hi; + int cost_lo = runp->cost_lo + current->cost_lo; + struct derivation_step *step; + + /* We managed to find a derivation. First see whether + this is what we are looking for. */ + if (strcmp (result_set, toset) == 0 + || (toset_expand != NULL + && strcmp (result_set, toset_expand) == 0)) { - /* Compile the regular expression if necessary. */ - if (runp->from_regex == NULL) + if (solution == NULL || cost_hi < best_cost_hi + || (cost_hi == best_cost_hi + && cost_lo < best_cost_lo)) { - if (__regcomp (&runp->from_regex_mem, - runp->from_pattern, - REG_EXTENDED | REG_ICASE) != 0) - /* Something is wrong. Remember this. */ - runp->from_regex = (regex_t *) -1L; - else - runp->from_regex = &runp->from_regex_mem; + best_cost_hi = cost_hi; + best_cost_lo = cost_lo; } - if (runp->from_regex != (regex_t *) -1L) + /* Append this solution to list. */ + if (solution == NULL) + solution = NEW_STEP (result_set, 0, 0, runp, current); + else { - regmatch_t match[4]; + while (solution->next != NULL) + solution = solution->next; - /* Try to match the regular expression. */ - if (__regexec (runp->from_regex, current->result_set, - 4, match, 0) == 0 - && match[0].rm_so == 0 - && current->result_set[match[0].rm_eo] == '\0') - { - /* At least the whole <from> string is matched. - We must now match sed-like possible - subexpressions from the match to the - toset expression. */ -#define ENSURE_LEN(LEN) \ - if (wp + (LEN) >= constr + len - 1) \ - { \ - char *newp = alloca (len += 128); \ - wp = __mempcpy (newp, constr, wp - constr); \ - constr = newp; \ - } - size_t len = 128; - char *constr = alloca (len); - char *wp = constr; - const char *cp = runp->to_string; - - while (*cp != '\0') - { - if (*cp != '\\') - { - ENSURE_LEN (1); - *wp++ = *cp++; - } - else if (cp[1] == '\0') - /* Backslash at end of string. */ - break; - else - { - ++cp; - if (*cp == '\\') - { - *wp++ = *cp++; - ENSURE_LEN (1); - } - else if (*cp < '1' || *cp > '3') - break; - else - { - int idx = *cp - '0'; - if (match[idx].rm_so == -1) - /* No match. */ - break; - - ENSURE_LEN (match[idx].rm_eo - - match[idx].rm_so); - wp = __mempcpy (wp, - ¤t->result_set[match[idx].rm_so], - match[idx].rm_eo - - match[idx].rm_so); - ++cp; - } - } - } - if (*cp == '\0' && wp != constr) - { - /* Terminate the constructed string. */ - *wp = '\0'; - result_set = constr; - } - } + solution->next = NEW_STEP (result_set, 0, 0, + runp, current); } } - - if (result_set != NULL) + else if (cost_hi < best_cost_hi + || (cost_hi == best_cost_hi + && cost_lo < best_cost_lo)) { - int cost_hi = runp->cost_hi + current->cost_hi; - int cost_lo = runp->cost_lo + current->cost_lo; - struct derivation_step *step; - - /* We managed to find a derivation. First see whether - this is what we are looking for. */ - if (strcmp (result_set, toset) == 0 - || (toset_expand != NULL - && strcmp (result_set, toset_expand) == 0)) - { - if (solution == NULL || cost_hi < best_cost_hi - || (cost_hi == best_cost_hi - && cost_lo < best_cost_lo)) - { - best_cost_hi = cost_hi; - best_cost_lo = cost_lo; - } + /* Append at the end if there is no entry with + this name. */ + for (step = first; step != NULL; step = step->next) + if (strcmp (result_set, step->result_set) == 0) + break; - /* Append this solution to list. */ - if (solution == NULL) - solution = NEW_STEP (result_set, 0, 0, runp, - current); - else - { - while (solution->next != NULL) - solution = solution->next; - - solution->next = NEW_STEP (result_set, 0, 0, - runp, current); - } + if (step == NULL) + { + *lastp = NEW_STEP (result_set, + cost_hi, cost_lo, + runp, current); + lastp = &(*lastp)->next; } - else if (cost_hi < best_cost_hi - || (cost_hi == best_cost_hi - && cost_lo < best_cost_lo)) + else if (step->cost_hi > cost_hi + || (step->cost_hi == cost_hi + && step->cost_lo > cost_lo)) { - /* Append at the end if there is no entry with - this name. */ - for (step = first; step != NULL; step = step->next) - if (strcmp (result_set, step->result_set) == 0) - break; + step->code = runp; + step->last = current; - if (step == NULL) + /* Update the cost for all steps. */ + for (step = first; step != NULL; + step = step->next) { - *lastp = NEW_STEP (result_set, - cost_hi, cost_lo, - runp, current); - lastp = &(*lastp)->next; - } - else if (step->cost_hi > cost_hi - || (step->cost_hi == cost_hi - && step->cost_lo > cost_lo)) - { - step->code = runp; - step->last = current; + struct derivation_step *back; + + if (step->code == NULL) + /* This is one of the entries we started + from. */ + continue; + + step->cost_hi = step->code->cost_hi; + step->cost_lo = step->code->cost_lo; - /* Update the cost for all steps. */ - for (step = first; step != NULL; - step = step->next) + for (back = step->last; back->code != NULL; + back = back->last) { - struct derivation_step *back; - - if (step->code == NULL) - /* This is one of the entries we started - from. */ - continue; - - step->cost_hi = step->code->cost_hi; - step->cost_lo = step->code->cost_lo; - - for (back = step->last; back->code != NULL; - back = back->last) - { - step->cost_hi += back->code->cost_hi; - step->cost_lo += back->code->cost_lo; - } + step->cost_hi += back->code->cost_hi; + step->cost_lo += back->code->cost_lo; } + } - for (step = solution; step != NULL; - step = step->next) + for (step = solution; step != NULL; + step = step->next) + { + step->cost_hi = (step->code->cost_hi + + step->last->cost_hi); + step->cost_lo = (step->code->cost_lo + + step->last->cost_lo); + + if (step->cost_hi < best_cost_hi + || (step->cost_hi == best_cost_hi + && step->cost_lo < best_cost_lo)) { - step->cost_hi = (step->code->cost_hi - + step->last->cost_hi); - step->cost_lo = (step->code->cost_lo - + step->last->cost_lo); - - if (step->cost_hi < best_cost_hi - || (step->cost_hi == best_cost_hi - && step->cost_lo < best_cost_lo)) - { - solution = step; - best_cost_hi = step->cost_hi; - best_cost_lo = step->cost_lo; - } + solution = step; + best_cost_hi = step->cost_hi; + best_cost_lo = step->cost_lo; } } } @@ -599,10 +489,7 @@ find_derivation (const char *toset, const char *toset_expand, } while (runp != NULL); - if (current->result_set_len == node->from_constpfx_len) - break; - - node = node->matching; + break; } else if (cmpres < 0) node = node->left; @@ -738,12 +625,10 @@ free_modules_db (struct gconv_module *node) free_modules_db (node->left); if (node->right != NULL) free_modules_db (node->right); - if (node->same != NULL) - free_modules_db (node->same); do { struct gconv_module *act = node; - node = node->matching; + node = node->same; if (act->module_name[0] == '/') free (act); } |