summary refs log tree commit diff
path: root/iconv
diff options
context:
space:
mode:
Diffstat (limited to 'iconv')
-rw-r--r--iconv/gconv_builtin.h43
-rw-r--r--iconv/gconv_conf.c199
-rw-r--r--iconv/gconv_db.c271
-rw-r--r--iconv/gconv_int.h9
-rw-r--r--iconv/iconv_prog.c25
5 files changed, 145 insertions, 402 deletions
diff --git a/iconv/gconv_builtin.h b/iconv/gconv_builtin.h
index 351d6a0342..185dd80125 100644
--- a/iconv/gconv_builtin.h
+++ b/iconv/gconv_builtin.h
@@ -29,21 +29,17 @@ BUILTIN_ALIAS ("OSF00010104//", "ISO-10646/UCS4/") /* level 1 */
 BUILTIN_ALIAS ("OSF00010105//", "ISO-10646/UCS4/") /* level 2 */
 BUILTIN_ALIAS ("OSF00010106//", "ISO-10646/UCS4/") /* level 3 */
 
-BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8,
-			"ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
+BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS4/", 1, "=INTERNAL->ucs4",
 			__gconv_transform_internal_ucs4, NULL, NULL,
 			4, 4, 4, 4)
-BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS4/", 15,
-			"INTERNAL", 1, "=ucs4->INTERNAL",
+BUILTIN_TRANSFORMATION ("ISO-10646/UCS4/", "INTERNAL", 1, "=ucs4->INTERNAL",
 			__gconv_transform_ucs4_internal, NULL, NULL,
 			4, 4, 4, 4)
 
-BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8,
-			"UCS-4LE//", 1, "=INTERNAL->ucs4le",
+BUILTIN_TRANSFORMATION ("INTERNAL", "UCS-4LE//", 1, "=INTERNAL->ucs4le",
 			__gconv_transform_internal_ucs4le, NULL, NULL,
 			4, 4, 4, 4)
-BUILTIN_TRANSFORMATION (NULL, "UCS-4LE//", 15,
-			"INTERNAL", 1, "=ucs4le->INTERNAL",
+BUILTIN_TRANSFORMATION ("UCS-4LE//", "INTERNAL", 1, "=ucs4le->INTERNAL",
 			__gconv_transform_ucs4le_internal, NULL, NULL,
 			4, 4, 4, 4)
 
@@ -52,13 +48,14 @@ BUILTIN_ALIAS ("UTF-8//", "ISO-10646/UTF8/")
 BUILTIN_ALIAS ("ISO-IR-193//", "ISO-10646/UTF8/")
 BUILTIN_ALIAS ("OSF05010001//", "ISO-10646/UTF8/")
 
-BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8,
-			"ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
+BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UTF8/", 1, "=INTERNAL->utf8",
 			__gconv_transform_internal_utf8, NULL, NULL,
 			4, 4, 1, 6)
 
-BUILTIN_TRANSFORMATION ("ISO-10646/UTF-?8/", "ISO-10646/UTF", 13,
-			"INTERNAL", 1, "=utf8->INTERNAL",
+BUILTIN_TRANSFORMATION ("ISO-10646/UTF-8/", "INTERNAL", 1, "=utf8->INTERNAL",
+			__gconv_transform_utf8_internal, NULL, NULL,
+			1, 6, 4, 4)
+BUILTIN_TRANSFORMATION ("ISO-10646/UTF8/", "INTERNAL", 1, "=utf8->INTERNAL",
 			__gconv_transform_utf8_internal, NULL, NULL,
 			1, 6, 4, 4)
 
@@ -68,13 +65,11 @@ BUILTIN_ALIAS ("OSF00010100//", "ISO-10646/UCS2/") /* level 1 */
 BUILTIN_ALIAS ("OSF00010101//", "ISO-10646/UCS2/") /* level 2 */
 BUILTIN_ALIAS ("OSF00010102//", "ISO-10646/UCS2/") /* level 3 */
 
-BUILTIN_TRANSFORMATION (NULL, "ISO-10646/UCS2/", 15, "INTERNAL",
-			1, "=ucs2->INTERNAL",
+BUILTIN_TRANSFORMATION ("ISO-10646/UCS2/", "INTERNAL", 1, "=ucs2->INTERNAL",
 			__gconv_transform_ucs2_internal, NULL, NULL,
 			2, 2, 4, 4)
 
-BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "ISO-10646/UCS2/",
-			1, "=INTERNAL->ucs2",
+BUILTIN_TRANSFORMATION ("INTERNAL", "ISO-10646/UCS2/", 1, "=INTERNAL->ucs2",
 			__gconv_transform_internal_ucs2, NULL, NULL,
 			4, 4, 2, 2)
 
@@ -85,13 +80,13 @@ BUILTIN_ALIAS ("UCS-2BE//", "ISO-10646/UCS2/")
 
 BUILTIN_ALIAS ("UCS-2LE//", "UNICODELITTLE//")
 
-BUILTIN_TRANSFORMATION (NULL, "UNICODELITTLE//", 15, "INTERNAL",
-			1, "=ucs2reverse->INTERNAL",
+BUILTIN_TRANSFORMATION ("UNICODELITTLE//", "INTERNAL", 1,
+			"=ucs2reverse->INTERNAL",
 			__gconv_transform_ucs2reverse_internal, NULL, NULL,
 			2, 2, 4, 4)
 
-BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "UNICODELITTLE//",
-			1, "=INTERNAL->ucs2reverse",
+BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODELITTLE//", 1,
+			"=INTERNAL->ucs2reverse",
 			__gconv_transform_internal_ucs2reverse, NULL, NULL,
 			4, 4, 2, 2)
 #else
@@ -100,13 +95,13 @@ BUILTIN_ALIAS ("UCS-2LE//", "ISO-10646/UCS2/")
 
 BUILTIN_ALIAS ("UCS-2BE//", "UNICODEBIG//")
 
-BUILTIN_TRANSFORMATION (NULL, "UNICODEBIG//", 12, "INTERNAL",
-			1, "=ucs2reverse->INTERNAL",
+BUILTIN_TRANSFORMATION ("UNICODEBIG//", "INTERNAL", 1,
+			"=ucs2reverse->INTERNAL",
 			__gconv_transform_ucs2reverse_internal, NULL, NULL,
 			2, 2, 4, 4)
 
-BUILTIN_TRANSFORMATION (NULL, "INTERNAL", 8, "UNICODEBIG//",
-			1, "=INTERNAL->ucs2reverse",
+BUILTIN_TRANSFORMATION ("INTERNAL", "UNICODEBIG//", 1,
+			"=INTERNAL->ucs2reverse",
 			__gconv_transform_internal_ucs2reverse, NULL, NULL,
 			4, 4, 2, 2)
 #endif
diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
index 480b459134..83d962129f 100644
--- a/iconv/gconv_conf.c
+++ b/iconv/gconv_conf.c
@@ -56,13 +56,10 @@ static const char gconv_module_ext[] = MODULE_EXT;
 /* We have a few builtin transformations.  */
 static struct gconv_module builtin_modules[] =
 {
-#define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \
-			       Fct, Init, End, MinF, MaxF, MinT, MaxT) \
+#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
+			       MaxF, MinT, MaxT) \
   {									      \
-    from_pattern: From,							      \
-    from_constpfx: ConstPfx,						      \
-    from_constpfx_len: ConstLen,					      \
-    from_regex: NULL,							      \
+    from_string: From,							      \
     to_string: To,							      \
     cost_hi: Cost,							      \
     cost_lo: INT_MAX,							      \
@@ -78,8 +75,8 @@ static struct gconv_module builtin_modules[] =
 
 static const char *builtin_aliases[] =
 {
-#define BUILTIN_TRANSFORMATION(From, ConstPfx, ConstLen, To, Cost, Name, \
-			       Fct, Init, End, MinF, MaxF, MinT, MaxT)
+#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, Init, End, MinF, \
+			       MaxF, MinT, MaxT)
 #define BUILTIN_ALIAS(From, To) From " " To,
 
 #include "gconv_builtin.h"
@@ -94,74 +91,17 @@ static const char *builtin_aliases[] =
 /* Test whether there is already a matching module known.  */
 static int
 internal_function
-detect_conflict (const char *alias, size_t alias_len)
+detect_conflict (const char *alias)
 {
   struct gconv_module *node = __gconv_modules_db;
 
   while (node != NULL)
     {
-      int cmpres = strncmp (alias, node->from_constpfx,
-			    MIN (alias_len, node->from_constpfx_len));
+      int cmpres = strcmp (alias, node->from_string);
 
       if (cmpres == 0)
-	{
-	  struct gconv_module *runp;
-
-	  if (alias_len < node->from_constpfx_len)
-	    /* Cannot possibly match.  */
-	    return 0;
-
-	  /* This means the prefix and the alias are identical.  If
-	     there is now a simple extry or a regular expression
-	     matching this name we have found a conflict.  If there is
-	     no conflict with the elements in the `same' list there
-	     cannot be a conflict.  */
-	  runp = node;
-	  do
-	    {
-	      if (runp->from_pattern == NULL)
-		{
-		  /* This is a simple entry and therefore we have a
-		     conflict if the strings are really the same.  */
-		  if (alias_len == node->from_constpfx_len)
-		    return 1;
-		}
-	      else
-		{
-		  /* Compile the regular expression if necessary.  */
-		  if (runp->from_regex == NULL)
-		    {
-		      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;
-		    }
-
-		  if (runp->from_regex != (regex_t *) -1L)
-		    {
-		      regmatch_t match[1];
-
-		      /* Try to match the regular expression.  */
-		      if (__regexec (runp->from_regex, alias, 1, match, 0) == 0
-			  && match[0].rm_so == 0
-			  && alias[match[0].rm_eo] == '\0')
-			/* They match, therefore it is a conflict.  */
-			return 1;
-		    }
-		}
-
-	      runp = runp->same;
-	    }
-	  while (runp != NULL);
-
-	  if (alias_len == node->from_constpfx_len)
-	      return 0;
-
-	  node = node->matching;
-	}
+	/* We have a conflict.  */
+	return 1;
       else if (cmpres < 0)
 	node = node->left;
       else
@@ -201,7 +141,7 @@ add_alias (char *rp, void *modules)
   *wp++ = '\0';
 
   /* Test whether this alias conflicts with any available module.  */
-  if (detect_conflict (from, to - from - 1))
+  if (detect_conflict (from))
     /* It does conflict, don't add the alias.  */
     return;
 
@@ -235,49 +175,27 @@ insert_module (struct gconv_module *newp)
   while (*rootp != NULL)
     {
       struct gconv_module *root = *rootp;
-      size_t minlen = MIN (newp->from_constpfx_len, root->from_constpfx_len);
       int cmpres;
 
-      cmpres = strncmp (newp->from_constpfx, root->from_constpfx, minlen);
+      cmpres = strcmp (newp->from_string, root->from_string);
       if (cmpres == 0)
 	{
-	  /* This can mean two things: the prefix is entirely the same or
-	     it matches only for the minimum length of both strings.  */
-	  if (newp->from_constpfx_len == root->from_constpfx_len)
+	  /* Both strings are identical.  Insert the string at the
+	     end of the `same' list if it is not already there.  */
+	  while (strcmp (newp->from_string, root->from_string) != 0
+		 || strcmp (newp->to_string, root->to_string) != 0)
 	    {
-	      /* Both prefixes are identical.  Insert the string at the
-		 end of the `same' list if it is not already there.  */
-	      const char *from_pattern = (newp->from_pattern
-					  ?: newp->from_constpfx);
-
-	      while (strcmp (from_pattern,
-			     root->from_pattern ?: root->from_constpfx) != 0
-		     || strcmp (newp->to_string, root->to_string) != 0)
-		{
-		  rootp = &root->same;
-		  root = *rootp;
-		  if (root == NULL)
-		    break;
-		}
-
-	      if (root != NULL)
-		/* This is a no new conversion.  */
-		return;
-
-	      break;
+	      rootp = &root->same;
+	      root = *rootp;
+	      if (root == NULL)
+		break;
 	    }
 
-	  /* The new element either has a prefix which is itself a
-	     prefix for the prefix of the current node or vice verse.
-	     In the first case we insert the node right here.  Otherwise
-	     we have to descent further.  */
-	  if (newp->from_constpfx_len < root->from_constpfx_len)
-	    {
-	      newp->matching = root;
-	      break;
-	    }
+	  if (root != NULL)
+	    /* This is a no new conversion.  */
+	    return;
 
-	  rootp = &root->matching;
+	  break;
 	}
       else if (cmpres < 0)
 	rootp = &root->left;
@@ -291,7 +209,7 @@ insert_module (struct gconv_module *newp)
 
 
 /* Add new module.  */
-static inline void
+static void
 internal_function
 add_module (char *rp, const char *directory, size_t dir_len, void **modules,
 	    size_t *nmodules, int modcounter)
@@ -302,22 +220,17 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
      3. filename of the module
      4. an optional cost value
   */
+  struct gconv_alias fake_alias;
   struct gconv_module *new_module;
   char *from, *to, *module, *wp;
-  size_t const_len;
-  int from_is_regex;
   int need_ext;
   int cost_hi;
 
   while (isspace (*rp))
     ++rp;
   from = rp;
-  from_is_regex = 0;
   while (*rp != '\0' && !isspace (*rp))
     {
-      if (!isalnum (*rp) && *rp != '-' && *rp != '/' && *rp != '.'
-	  && *rp != '_' && *rp != '(' && *rp != ')')
-	from_is_regex = 1;
       *rp = toupper (*rp);
       ++rp;
     }
@@ -373,18 +286,12 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
     /* We must add the module extension.  */
     need_ext = sizeof (gconv_module_ext) - 1;
 
-  /* We've collected all the information, now create an entry.  */
+  /* See whether we have already an alias with this name defined.  */
+  fake_alias.fromname = strndupa (from, to - from);
 
-  if (from_is_regex)
-    {
-      const_len = 0;
-      while (isalnum (from[const_len]) || from[const_len] == '-'
-	     || from[const_len] == '/' || from[const_len] == '.'
-	     || from[const_len] == '_')
-	++const_len;
-    }
-  else
-    const_len = to - from - 1;
+  if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare) != NULL)
+    /* This module duplicates an alias.  */
+    return;
 
   new_module = (struct gconv_module *) calloc (1,
 					       sizeof (struct gconv_module)
@@ -394,15 +301,11 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
     {
       char *tmp;
 
-      new_module->from_constpfx = memcpy ((char *) new_module
-					  + sizeof (struct gconv_module),
-					  from, to - from);
-      if (from_is_regex)
-	new_module->from_pattern = new_module->from_constpfx;
+      new_module->from_string = memcpy ((char *) new_module
+					+ sizeof (struct gconv_module),
+					from, to - from);
 
-      new_module->from_constpfx_len = const_len;
-
-      new_module->to_string = memcpy ((char *) new_module->from_constpfx
+      new_module->to_string = memcpy ((char *) new_module->from_string
 				      + (to - from), to, module - to);
 
       new_module->cost_hi = cost_hi;
@@ -424,25 +327,6 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
       if (need_ext)
 	memcpy (tmp - 1, gconv_module_ext, sizeof (gconv_module_ext));
 
-      /* See whether we have already an alias with this name defined.
-	 We do allow regular expressions matching this any alias since
-	 this expression can also match other names and we test for aliases
-	 before testing for modules.  */
-      if (! from_is_regex)
-	{
-	  struct gconv_alias fake_alias;
-
-	  fake_alias.fromname = new_module->from_constpfx;
-
-	  if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
-	      != NULL)
-	    {
-	      /* This module duplicates an alias.  */
-	      free (new_module);
-	      return;
-	    }
-	}
-
       /* Now insert the new module data structure in our search tree.  */
       insert_module (new_module);
     }
@@ -643,17 +527,14 @@ __gconv_read_conf (void)
   for (cnt = 0; cnt < sizeof (builtin_modules) / sizeof (builtin_modules[0]);
        ++cnt)
     {
-      if (builtin_modules[cnt].from_pattern == NULL)
-	{
-	  struct gconv_alias fake_alias;
+      struct gconv_alias fake_alias;
 
-	  fake_alias.fromname = builtin_modules[cnt].from_constpfx;
+      fake_alias.fromname = builtin_modules[cnt].from_string;
 
-	  if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
-	      != NULL)
-	    /* It'll conflict so don't add it.  */
-	    continue;
-	}
+      if (__tfind (&fake_alias, &__gconv_alias_db, __gconv_alias_compare)
+	  != NULL)
+	/* It'll conflict so don't add it.  */
+	continue;
 
       insert_module (&builtin_modules[cnt]);
     }
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);
     }
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
index 6d199715ca..44d4d36445 100644
--- a/iconv/gconv_int.h
+++ b/iconv/gconv_int.h
@@ -21,7 +21,6 @@
 #define _GCONV_INT_H	1
 
 #include "gconv.h"
-#include <regex.h>
 
 __BEGIN_DECLS
 
@@ -76,12 +75,7 @@ struct __gconv_loaded_object
 /* Description for an available conversion module.  */
 struct gconv_module
 {
-  const char *from_pattern;
-  const char *from_constpfx;
-  size_t from_constpfx_len;
-  const regex_t *from_regex;
-  regex_t from_regex_mem;
-
+  const char *from_string;
   const char *to_string;
 
   int cost_hi;
@@ -91,7 +85,6 @@ struct gconv_module
 
   struct gconv_module *left;	/* Prefix smaller.  */
   struct gconv_module *same;	/* List of entries with identical prefix.  */
-  struct gconv_module *matching;/* Next node with more specific prefix.  */
   struct gconv_module *right;	/* Prefix larger.  */
 };
 
diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c
index 9c85b7ce69..d8e7817dd9 100644
--- a/iconv/iconv_prog.c
+++ b/iconv/iconv_prog.c
@@ -595,23 +595,15 @@ add_known_names (struct gconv_module *node)
     add_known_names (node->left);
   if (node->right != NULL)
     add_known_names (node->right);
-  if (node->same != NULL)
-    add_known_names (node->same);
   do
     {
-      if (node->from_pattern == NULL)
-	{
-	  if (strcmp (node->from_constpfx, "INTERNAL"))
-	    tsearch (node->from_constpfx, &printlist,
-		     (__compar_fn_t) strverscmp);
-	  if (strcmp (node->to_string, "INTERNAL"))
-	    tsearch (node->to_string, &printlist, (__compar_fn_t) strverscmp);
-	}
-      else
-	if (strcmp (node->from_pattern, "INTERNAL"))
-	  tsearch (node->from_pattern, &printlist, (__compar_fn_t) strverscmp);
+      if (strcmp (node->from_string, "INTERNAL"))
+	tsearch (node->from_string, &printlist,
+		 (__compar_fn_t) strverscmp);
+      if (strcmp (node->to_string, "INTERNAL"))
+	tsearch (node->to_string, &printlist, (__compar_fn_t) strverscmp);
 
-      node = node->matching;
+      node = node->same;
     }
   while (node != NULL);
 }
@@ -636,10 +628,7 @@ print_known_names (void)
 The following list contain all the coded character sets known.  This does\n\
 not necessarily mean that all combinations of these names can be used for\n\
 the FROM and TO command line parameters.  One coded character set can be\n\
-listed with several different names (aliases).\n\
-  Some of the names are no plain strings but instead regular expressions and\n\
-they match a variety of names which can be given as parameters to the\n\
-program.\n\n  "), stdout);
+listed with several different names (aliases).\n\n  "), stdout);
 
   /* Now print the collected names.  */
   column = 2;