aboutsummaryrefslogtreecommitdiff
path: root/iconv/gconv_db.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconv/gconv_db.c')
-rw-r--r--iconv/gconv_db.c271
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,
- &current->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);
}