summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-06-20 00:34:21 +0000
committerUlrich Drepper <drepper@redhat.com>2000-06-20 00:34:21 +0000
commitd2dfc5de011fb525161b85a1408f716a2ea358cc (patch)
tree22804aa59f348ac9d5bf432d2ddeb4c79ad31910
parentd620426811688301eb1cbe6e63773d6430b2706e (diff)
downloadglibc-d2dfc5de011fb525161b85a1408f716a2ea358cc.tar.gz
glibc-d2dfc5de011fb525161b85a1408f716a2ea358cc.tar.xz
glibc-d2dfc5de011fb525161b85a1408f716a2ea358cc.zip
Update.
	* iconv/gconv_int.h (strict gconv_module): Remove all members
	associated with regular expressions.  Use a simple string as the
	from name.
	* iconv/gconv_db.c: Remove code handling regular expressions.
	* iconv/gconv_conf.c: Likewise.
	* iconv/iconv_prog.c: Likewise.
	* iconv/gconv_builtin.h: Adjust for change in gconv_conf.c.
-rw-r--r--ChangeLog8
-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
-rw-r--r--linuxthreads/ChangeLog33
-rw-r--r--linuxthreads/sysdeps/pthread/posix-timer.h28
-rw-r--r--linuxthreads/sysdeps/pthread/timer_getoverr.c4
-rw-r--r--linuxthreads/sysdeps/pthread/timer_gettime.c35
-rw-r--r--linuxthreads/sysdeps/pthread/timer_routines.c12
-rw-r--r--linuxthreads/sysdeps/pthread/timer_settime.c13
12 files changed, 249 insertions, 431 deletions
diff --git a/ChangeLog b/ChangeLog
index 8b8305a9ed..d8cc30ce47 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2000-06-19  Ulrich Drepper  <drepper@redhat.com>
 
+	* iconv/gconv_int.h (strict gconv_module): Remove all members
+	associated with regular expressions.  Use a simple string as the
+	from name.
+	* iconv/gconv_db.c: Remove code handling regular expressions.
+	* iconv/gconv_conf.c: Likewise.
+	* iconv/iconv_prog.c: Likewise.
+	* iconv/gconv_builtin.h: Adjust for change in gconv_conf.c.
+
 	* iconv/gconv.h (__gconv_trans_fct): Add new parameter.
 	General namespace cleanup.
 	(struct __gconv_trans_data): Add next field.
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;
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 2322ca91e6..0402c0fdfe 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,36 @@
+2000-06-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/pthread/timer_create.c: Use _set_errno instead of assigning
+	to errno directly.
+	* sysdeps/pthread/timer_delete.c: Likewise.
+	* sysdeps/pthread/timer_getoverr.c: Likewise.
+	* sysdeps/pthread/timer_gettime.c: Likewise.
+	* sysdeps/pthread/timer_settime.c: Likewise.
+
+2000-06-13  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+	Timer nodes are now reference counted, and can be marked
+	as deleted. This allows for the safe release of the global mutex
+	in the middle without losing the timer being operated on.
+
+	* sysdeps/pthread/posix-timer.h (struct timer_node):  The inuse
+	member is now an enum with three values, so that an intermediate
+	state can be represented (deleted but not free for reuse yet).
+	New refcount member added.
+	* sysdeps/pthread/timer_routines.c: Likewise.
+
+	* sysdeps/pthread/posix-timer.h (timer_addref, timer_delref,
+	timer_valid): New inline functions added.
+
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): Function
+	restructured, recursive deadlock bug fixed.
+
+	* sysdeps/pthread/timer_gettime.c (timer_gettime): Uses new
+	timer_addref to ensure that timer won't be deleted while mutex is not
+	held. Also uses timer_invalid to perform validation of timer handle.
+	* sysdeps/pthread/timer_settime.c (timer_settime): Likewise.
+	* sysdeps/pthread/timer_getoverr.c (timer_getoverrun): Likewise.
+
 2000-06-14  Ulrich Drepper  <drepper@redhat.com>
 
 	* shlib-versions: Add entry for SH.
diff --git a/linuxthreads/sysdeps/pthread/posix-timer.h b/linuxthreads/sysdeps/pthread/posix-timer.h
index feeff39fa8..7a2caf28a4 100644
--- a/linuxthreads/sysdeps/pthread/posix-timer.h
+++ b/linuxthreads/sysdeps/pthread/posix-timer.h
@@ -59,9 +59,12 @@ struct timer_node
   pthread_attr_t attr;
   unsigned int abstime;
   unsigned int armed;
-  unsigned int inuse;
+  enum {
+    TIMER_FREE, TIMER_INUSE, TIMER_DELETED
+  } inuse;
   struct thread_node *thread;
   pid_t creator_pid;
+  int refcount;
 };
 
 
@@ -106,6 +109,28 @@ timer_ptr2id (struct timer_node *timer)
   return timer - __timer_array;
 }
 
+/* Check whether timer is valid; global mutex must be held. */
+static inline int
+timer_valid (struct timer_node *timer)
+{
+  return timer && timer->inuse == TIMER_INUSE;
+}
+
+/* Timer refcount functions; need global mutex. */
+extern void __timer_dealloc (struct timer_node *timer);
+
+static inline void
+timer_addref (struct timer_node *timer)
+{
+  timer->refcount++;
+}
+
+static inline void
+timer_delref (struct timer_node *timer)
+{
+  if (--timer->refcount == 0)
+    __timer_dealloc (timer);
+}
 
 /* Timespec helper routines.  */
 static inline int
@@ -178,7 +203,6 @@ extern struct timer_node *__timer_alloc (void);
 extern int __timer_thread_start (struct thread_node *thread);
 extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t);
 extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t);
-extern void __timer_dealloc (struct timer_node *timer);
 extern void __timer_thread_dealloc (struct thread_node *thread);
 extern int __timer_thread_queue_timer (struct thread_node *thread,
 				       struct timer_node *insert);
diff --git a/linuxthreads/sysdeps/pthread/timer_getoverr.c b/linuxthreads/sysdeps/pthread/timer_getoverr.c
index 8630f57829..520458c712 100644
--- a/linuxthreads/sysdeps/pthread/timer_getoverr.c
+++ b/linuxthreads/sysdeps/pthread/timer_getoverr.c
@@ -34,8 +34,8 @@ timer_getoverrun (timerid)
 
   pthread_mutex_lock (&__timer_mutex);
 
-  if ((timer = timer_id2ptr (timerid)) == NULL || !timer->inuse)
-    errno = EINVAL;
+  if (! timer_valid (timer = timer_id2ptr (timerid)))
+    __set_errno (EINVAL);
   else
     retval = 0; /* TODO: overrun counting not supported */
 
diff --git a/linuxthreads/sysdeps/pthread/timer_gettime.c b/linuxthreads/sysdeps/pthread/timer_gettime.c
index 43b07598b7..dbee9d915e 100644
--- a/linuxthreads/sysdeps/pthread/timer_gettime.c
+++ b/linuxthreads/sysdeps/pthread/timer_gettime.c
@@ -31,25 +31,30 @@ timer_gettime (timerid, value)
      struct itimerspec *value;
 {
   struct timer_node *timer;
-  struct timespec now;
-  int retval = -1;
+  struct timespec now, expiry;
+  int retval = -1, armed = 0, valid;
+  clock_t clock = 0;
 
   pthread_mutex_lock (&__timer_mutex);
 
   timer = timer_id2ptr (timerid);
-  if (timer == NULL && !timer->inuse)
-    /* Invalid timer ID or the timer is not in use.  */
-    errno = EINVAL;
-  else
-    {
-      value->it_interval = timer->value.it_interval;
+  valid = timer_valid (timer);
+
+  if (valid) {
+    armed = timer->armed;
+    expiry = timer->expirytime;
+    clock = timer->clock;
+    value->it_interval = timer->value.it_interval;
+  }
+
+  pthread_mutex_unlock (&__timer_mutex);
 
-      if (timer->armed)
+  if (valid)
+    {
+      if (armed)
 	{
-	  pthread_mutex_unlock (&__timer_mutex);
-	  clock_gettime (timer->clock, &now);
-	  pthread_mutex_lock (&__timer_mutex);
-	  timespec_sub (&value->it_value, &timer->expirytime, &now);
+	  clock_gettime (clock, &now);
+	  timespec_sub (&value->it_value, &expiry, &now);
 	}
       else
 	{
@@ -59,8 +64,8 @@ timer_gettime (timerid, value)
 
       retval = 0;
     }
-
-  pthread_mutex_lock (&__timer_mutex);
+  else
+    __set_errno (EINVAL);
 
   return retval;
 }
diff --git a/linuxthreads/sysdeps/pthread/timer_routines.c b/linuxthreads/sysdeps/pthread/timer_routines.c
index ddf02fadd6..2d4e325b6d 100644
--- a/linuxthreads/sysdeps/pthread/timer_routines.c
+++ b/linuxthreads/sysdeps/pthread/timer_routines.c
@@ -181,7 +181,7 @@ init_module (void)
   for (i = 0; i < TIMER_MAX; ++i)
     {
       list_append (&timer_free_list, &__timer_array[i].links);
-      __timer_array[i].inuse = 0;
+      __timer_array[i].inuse = TIMER_FREE;
     }
 
   for (i = 0; i < THREAD_MAXNODES; ++i)
@@ -309,7 +309,7 @@ thread_cleanup (void *val)
 static void
 thread_expire_timer (struct thread_node *self, struct timer_node *timer)
 {
-  self->current_timer = timer;
+  self->current_timer = timer; /* Lets timer_delete know timer is running. */
 
   pthread_mutex_unlock (&__timer_mutex);
 
@@ -443,7 +443,7 @@ thread_func (void *arg)
 }
 
 
-/* Enqueue a timer in wakeup order in the thread's timer queue. 
+/* Enqueue a timer in wakeup order in the thread's timer queue.
    Returns 1 if the timer was inserted at the head of the queue,
    causing the queue's next wakeup time to change. */
 
@@ -551,7 +551,8 @@ __timer_alloc (void)
     {
       struct timer_node *timer = timer_links2ptr (node);
       list_unlink_ip (node);
-      timer->inuse = 1;
+      timer->inuse = TIMER_INUSE;
+      timer->refcount = 1;
       return timer;
     }
 
@@ -564,8 +565,9 @@ __timer_alloc (void)
 void
 __timer_dealloc (struct timer_node *timer)
 {
+  assert (timer->refcount == 0);
   timer->thread = NULL;	/* Break association between timer and thread.  */
-  timer->inuse = 0;
+  timer->inuse = TIMER_FREE;
   list_append (&timer_free_list, &timer->links);
 }
 
diff --git a/linuxthreads/sysdeps/pthread/timer_settime.c b/linuxthreads/sysdeps/pthread/timer_settime.c
index 858edc7657..e6c35b4fcf 100644
--- a/linuxthreads/sysdeps/pthread/timer_settime.c
+++ b/linuxthreads/sysdeps/pthread/timer_settime.c
@@ -41,7 +41,7 @@ timer_settime (timerid, flags, value, ovalue)
   timer = timer_id2ptr (timerid);
   if (timer == NULL)
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       goto bail;
     }
 
@@ -50,7 +50,7 @@ timer_settime (timerid, flags, value, ovalue)
       || value->it_value.tv_nsec < 0
       || value->it_value.tv_nsec >= 1000000000)
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       goto bail;
     }
 
@@ -64,13 +64,14 @@ timer_settime (timerid, flags, value, ovalue)
     }
 
   pthread_mutex_lock (&__timer_mutex);
+  timer_addref (timer);
 
   /* One final check of timer validity; this one is possible only
-     until we have the mutex, which guards the inuse flag. */
+     until we have the mutex, because it accesses the inuse flag. */
 
-  if (!timer->inuse)
+  if (! timer_valid(timer))
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       goto unlock_bail;
     }
 
@@ -86,6 +87,7 @@ timer_settime (timerid, flags, value, ovalue)
 	      clock_gettime (timer->clock, &now);
 	      have_now = 1;
 	      pthread_mutex_lock (&__timer_mutex);
+	      timer_addref (timer);
 	    }
 
 	  timespec_sub (&ovalue->it_value, &timer->expirytime, &now);
@@ -123,6 +125,7 @@ timer_settime (timerid, flags, value, ovalue)
   retval = 0;
 
 unlock_bail:
+  timer_delref (timer);
   pthread_mutex_unlock (&__timer_mutex);
 
 bail: