about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--NEWS4
-rw-r--r--libio/fileops.c120
-rw-r--r--libio/iofclose.c12
-rw-r--r--libio/iofwide.c23
-rw-r--r--malloc/mtrace.pl13
-rw-r--r--wcsmbs/wcsmbsload.c88
-rw-r--r--wcsmbs/wcsmbsload.h4
8 files changed, 202 insertions, 80 deletions
diff --git a/ChangeLog b/ChangeLog
index 2b31c404e8..e7c8890dba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
 2001-07-27  Ulrich Drepper  <drepper@redhat.com>
 
+	* libio/fileops.c (_IO_new_file_fopen): Correctly locate ccs=
+	substring.  Don't handle ccs= if no descriptor was allocated.
+	Normalize codeset name before calling __wcsmbs_named_conv.
+	Initialize transliteration elements.  Free step data structure.
+	* libio/iofclose.c (_IO_new_fclose): Correct freeing of the step data.
+	* libio/iofwide.c (__libio_translit): Renamed from libio_translit
+	and made public.  Various little cleanup changes.
+	* wcsmbs/wcsmbsload.h (struct gconv_fcts): Add towc_nsteps and
+	tomb_nsteps member.
+	* wcsmbs/wcsmbsload.c: Add some casts to avoid warnings.
+	(__wcsmbs_gconv_fcts): Initialize towc_nsteps and tomb_nsteps member.
+	(getfct): Take additional parameter with pointer to variable where the
+	number of steps is stored in.  Disable code which allows to use more
+	than one step for now.  Adjust all callers.
+	(free_mem): New function.  Frees data associated with currently
+	selected converters.
+
 	* malloc/mtrace.pl: Extract addresses from DSOs.
 
 2001-07-26  Ulrich Drepper  <drepper@redhat.com>
@@ -29,7 +46,6 @@
 	* sysdeps/generic/tcsetattr.c (bad_speed): Accept those values.
 	* termios/cfsetspeed.c (speeds): Likewise.
 
->>>>>>> 1.5525
 2001-07-26  kaz Kojima  <kkojima@rr.iij4u.or.jp>
 
 	* sysdeps/sh/dl-machine.h (elf_machine_load_address): Don't use
diff --git a/NEWS b/NEWS
index c9039616a2..5144dc0610 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2001-7-25
+GNU C Library NEWS -- history of user-visible changes.  2001-7-27
 Copyright (C) 1992-2000, 2001 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -28,6 +28,8 @@ Version 2.2.4
 
 * The Hurd port got a lot more functionality like AIO, various stdio
   extensions, etc.  Mainly done by Roland McGrath.
+
+* mtrace can now lookup symbols in shared libraries.
 
 Version 2.2.3
 
diff --git a/libio/fileops.c b/libio/fileops.c
index 03f71d71c0..3947fa8d6c 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -31,6 +31,7 @@
 # define _POSIX_SOURCE
 #endif
 #include "libioP.h"
+#include <assert.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -42,6 +43,8 @@
 #endif
 #if _LIBC
 # include "../wcsmbs/wcsmbsload.h"
+# include "../iconv/gconv_charset.h"
+# include "../iconv/gconv_int.h"
 # include <shlib-compat.h>
 #endif
 #ifndef errno
@@ -74,6 +77,12 @@ extern int errno;
 # define _IO_new_file_xsputn _IO_file_xsputn
 #endif
 
+
+#ifdef _LIBC
+extern struct __gconv_trans_data __libio_translit;
+#endif
+
+
 /* An fstream can be in at most one of put mode, get mode, or putback mode.
    Putback mode is a variant of get mode.
 
@@ -238,8 +247,9 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
   int oprot = 0666;
   int i;
   _IO_FILE *result;
-#if _LIBC
+#ifdef _LIBC
   const char *cs;
+  const char *last_recognized;
 #endif
 
   if (_IO_file_is_open (fp))
@@ -264,6 +274,9 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
       __set_errno (EINVAL);
       return NULL;
     }
+#ifdef _LIBC
+  last_recognized = mode;
+#endif
   for (i = 1; i < 4; ++i)
     {
       switch (*++mode)
@@ -273,11 +286,20 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
 	case '+':
 	  omode = O_RDWR;
 	  read_write &= _IO_IS_APPENDING;
+#ifdef _LIBC
+	  last_recognized = mode;
+#endif
 	  continue;
 	case 'x':
 	  oflags |= O_EXCL;
+#ifdef _LIBC
+	  last_recognized = mode;
+#endif
 	  continue;
 	case 'b':
+#ifdef _LIBC
+	  last_recognized = mode;
+#endif
 	default:
 	  /* Ignore.  */
 	  continue;
@@ -289,48 +311,78 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
 			  is32not64);
 
 
-#if _LIBC
-  /* Test whether the mode string specifies the conversion.  */
-  cs = strstr (mode, ",ccs=");
-  if (cs != NULL)
+#ifdef _LIBC
+  if (result != NULL)
     {
-      /* Yep.  Load the appropriate conversions and set the orientation
-	 to wide.  */
-	struct gconv_fcts fcts;
-	struct _IO_codecvt *cc;
+      /* Test whether the mode string specifies the conversion.  */
+      cs = strstr (last_recognized + 1, ",ccs=");
+      if (cs != NULL)
+	{
+	  /* Yep.  Load the appropriate conversions and set the orientation
+	     to wide.  */
+	  struct gconv_fcts fcts;
+	  struct _IO_codecvt *cc;
+	  char *endp = __strchrnul (cs + 5, ',');
+	  char ccs[endp - (cs + 5) + 3];
+
+	  *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
+	  strip (ccs, ccs);
+
+	  if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
+				   ? upstr (ccs, cs + 5) : ccs) != 0)
+	    {
+	      /* Something went wrong, we cannot load the conversion modules.
+		 This means we cannot proceed since the user explicitly asked
+		 for these.  */
+	      __set_errno (EINVAL);
+	      return NULL;
+	    }
 
-	if (! _IO_CHECK_WIDE (fp) || __wcsmbs_named_conv (&fcts, cs + 5) != 0)
-	  {
-	    /* Something went wrong, we cannot load the conversion modules.
-	       This means we cannot proceed since the user explicitly asked
-	       for these.  */
-	    _IO_new_fclose (result);
-	    return NULL;
-	  }
+	  assert (fcts.towc_nsteps == 1);
+	  assert (fcts.tomb_nsteps == 1);
+
+	  fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
+	  fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
+
+	  /* Clear the state.  We start all over again.  */
+	  memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
+	  memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
+
+	  cc = fp->_codecvt = &fp->_wide_data->_codecvt;
 
-	cc = fp->_codecvt = &fp->_wide_data->_codecvt;
+	  /* The functions are always the same.  */
+	  *cc = __libio_codecvt;
 
-	/* The functions are always the same.  */
-	*cc = __libio_codecvt;
+	  cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
+	  cc->__cd_in.__cd.__steps = fcts.towc;
 
-	cc->__cd_in.__cd.__nsteps = 1; /* Only one step allowed.  */
-	cc->__cd_in.__cd.__steps = fcts.towc;
+	  cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
+	  cc->__cd_in.__cd.__data[0].__internal_use = 1;
+	  cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
+	  cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
 
-	cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
-	cc->__cd_in.__cd.__data[0].__internal_use = 1;
-	cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
-	cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
+	  /* XXX For now no transliteration.  */
+	  cc->__cd_in.__cd.__data[0].__trans = NULL;
 
-	cc->__cd_out.__cd.__nsteps = 1; /* Only one step allowed.  */
-	cc->__cd_out.__cd.__steps = fcts.tomb;
+	  cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
+	  cc->__cd_out.__cd.__steps = fcts.tomb;
 
-	cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
-	cc->__cd_out.__cd.__data[0].__internal_use = 1;
-	cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
-	cc->__cd_out.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
+	  cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
+	  cc->__cd_out.__cd.__data[0].__internal_use = 1;
+	  cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
+	  cc->__cd_out.__cd.__data[0].__statep =
+	    &result->_wide_data->_IO_state;
 
-	/* Set the mode now.  */
-	result->_mode = 1;
+	  /* And now the transliteration.  */
+	  cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
+
+	  /* Set the mode now.  */
+	  result->_mode = 1;
+
+	  /* We don't need the step data structure anymore.  */
+	  __gconv_release_cache (fcts.towc, fcts.towc_nsteps);
+	  __gconv_release_cache (fcts.tomb, fcts.tomb_nsteps);
+	}
     }
 #endif	/* GNU libc */
 
diff --git a/libio/iofclose.c b/libio/iofclose.c
index 660c118359..45bd0afa7d 100644
--- a/libio/iofclose.c
+++ b/libio/iofclose.c
@@ -72,16 +72,8 @@ _IO_new_fclose (fp)
 	 the conversion functions.  */
       struct _IO_codecvt *cc = fp->_codecvt;
 
-      if (cc->__cd_in.__cd.__steps->__shlib_handle != NULL)
-	{
-	  --cc->__cd_in.__cd.__steps->__counter;
-	  __gconv_close_transform (cc->__cd_in.__cd.__steps, 1);
-	}
-      if (cc->__cd_out.__cd.__steps->__shlib_handle != NULL)
-	{
-	  --cc->__cd_out.__cd.__steps->__counter;
-	  __gconv_close_transform (cc->__cd_out.__cd.__steps, 1);
-	}
+      __gconv_release_step (cc->__cd_in.__cd.__steps);
+      __gconv_release_step (cc->__cd_out.__cd.__steps);
 #endif
     }
   _IO_cleanup_region_end (0);
diff --git a/libio/iofwide.c b/libio/iofwide.c
index d191baaf99..aa314fe671 100644
--- a/libio/iofwide.c
+++ b/libio/iofwide.c
@@ -30,6 +30,7 @@
 # include <dlfcn.h>
 # include <wchar.h>
 #endif
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -81,7 +82,7 @@ struct _IO_codecvt __libio_codecvt =
 
 
 #ifdef _LIBC
-static struct __gconv_trans_data libio_translit =
+struct __gconv_trans_data __libio_translit =
 {
   .__trans_fct = __gconv_transliterate
 };
@@ -134,11 +135,13 @@ _IO_fwide (fp, mode)
 	memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
 
 	__wcsmbs_clone_conv (&fcts);
+	assert (fcts.towc_nsteps == 1);
+	assert (fcts.tomb_nsteps == 1);
 
 	/* The functions are always the same.  */
 	*cc = __libio_codecvt;
 
-	cc->__cd_in.__cd.__nsteps = 1; /* Only one step allowed.  */
+	cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
 	cc->__cd_in.__cd.__steps = fcts.towc;
 
 	cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
@@ -149,7 +152,7 @@ _IO_fwide (fp, mode)
 	/* XXX For now no transliteration.  */
 	cc->__cd_in.__cd.__data[0].__trans = NULL;
 
-	cc->__cd_out.__cd.__nsteps = 1; /* Only one step allowed.  */
+	cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
 	cc->__cd_out.__cd.__steps = fcts.tomb;
 
 	cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
@@ -158,11 +161,7 @@ _IO_fwide (fp, mode)
 	cc->__cd_out.__cd.__data[0].__statep = &fp->_wide_data->_IO_state;
 
 	/* And now the transliteration.  */
-#ifdef _LIBC
-	cc->__cd_out.__cd.__data[0].__trans = &libio_translit;
-#else
-	cc->__cd_out.__cd.__data[0].__trans = NULL;
-#endif
+	cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
       }
 #else
 # ifdef _GLIBCPP_USE_WCHAR_T
@@ -188,8 +187,12 @@ _IO_fwide (fp, mode)
 	  cc->__cd_out = iconv_open (external_ccs, internal_ccs);
 
 	if (cc->__cd_in == (iconv_t) -1 || cc->__cd_out == (iconv_t) -1)
-	  /* XXX */
-	  abort ();
+	  {
+	    if (cc->__cd_in != (iconv_t) -1)
+	      iconv_close (cc->__cd_in);
+	    /* XXX */
+	    abort ();
+	  }
       }
 # else
 #  error "somehow determine this from LC_CTYPE"
diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl
index e3ed5771dd..7e06c99f29 100644
--- a/malloc/mtrace.pl
+++ b/malloc/mtrace.pl
@@ -125,6 +125,19 @@ sub location {
 	    }
 	}
 	$cache{$addr} = $str = $addr;
+    } elsif ($str =~ /^.*[[](0x[^]]*)]$/) {
+	my $addr = $1;
+	return $cache{$addr} if (exists $cache{$addr});
+	if ($binary ne "" && open (ADDR, "addr2line -e $binary $addr|")) {
+	    my $line = <ADDR>;
+	    chomp $line;
+	    close (ADDR);
+	    if ($line ne '??:0') {
+		$cache{$addr} = $line;
+		return $cache{$addr};
+	    }
+	}
+	$cache{$addr} = $str = $addr;
     }
     return $str;
 }
diff --git a/wcsmbs/wcsmbsload.c b/wcsmbs/wcsmbsload.c
index f5d9426c32..c096804a68 100644
--- a/wcsmbs/wcsmbsload.c
+++ b/wcsmbs/wcsmbsload.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -41,8 +41,8 @@ static struct __gconv_step to_wc =
   .__shlib_handle = NULL,
   .__modname = NULL,
   .__counter = INT_MAX,
-  .__from_name = "ANSI_X3.4-1968//TRANSLIT",
-  .__to_name = "INTERNAL",
+  .__from_name = (char *) "ANSI_X3.4-1968//TRANSLIT",
+  .__to_name = (char *) "INTERNAL",
   .__fct = __gconv_transform_ascii_internal,
   .__init_fct = NULL,
   .__end_fct = NULL,
@@ -59,8 +59,8 @@ static struct __gconv_step to_mb =
   .__shlib_handle = NULL,
   .__modname = NULL,
   .__counter = INT_MAX,
-  .__from_name = "INTERNAL",
-  .__to_name = "ANSI_X3.4-1968//TRANSLIT",
+  .__from_name = (char *) "INTERNAL",
+  .__to_name = (char *) "ANSI_X3.4-1968//TRANSLIT",
   .__fct = __gconv_transform_internal_ascii,
   .__init_fct = NULL,
   .__end_fct = NULL,
@@ -77,22 +77,33 @@ static struct __gconv_step to_mb =
 struct gconv_fcts __wcsmbs_gconv_fcts =
 {
   .towc = &to_wc,
-  .tomb = &to_mb
+  .towc_nsteps = 1,
+  .tomb = &to_mb,
+  .tomb_nsteps = 1
 };
 
 
 static inline struct __gconv_step *
-getfct (const char *to, const char *from)
+getfct (const char *to, const char *from, size_t *nstepsp)
 {
   size_t nsteps;
   struct __gconv_step *result;
+#if 0
   size_t nstateful;
   size_t cnt;
+#endif
 
   if (__gconv_find_transform (to, from, &result, &nsteps, 0) != __GCONV_OK)
     /* Loading the conversion step is not possible.  */
     return NULL;
 
+  /* Maybe it is someday necessary to allow more than one step.
+     Currently this is not the case since the conversions handled here
+     are from and to INTERNAL and there always is a converted for
+     that.  It the directly following code is enabled the libio
+     functions will have to allocate appropriate __gconv_step_data
+     elements instead of only one.  */
+#if 0
   /* Count the number of stateful conversions.  Since we will only
      have one 'mbstate_t' object available we can only deal with one
      stateful conversion.  */
@@ -101,11 +112,16 @@ getfct (const char *to, const char *from)
     if (result[cnt].__stateful)
       ++nstateful;
   if (nstateful > 1)
+#else
+  if (nsteps > 1)
+#endif
     {
       /* We cannot handle this case.  */
       __gconv_close_transform (result, nsteps);
       result = NULL;
     }
+  else
+    *nstepsp = nsteps;
 
   return result;
 }
@@ -160,12 +176,18 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
 	  const char *charset_name;
 	  const char *complete_name;
 	  struct __gconv_step *new_towc;
+	  size_t new_towc_nsteps;
 	  struct __gconv_step *new_tomb;
+	  size_t new_tomb_nsteps;
 	  int use_translit;
 
 	  /* Free the old conversions.  */
-	  __gconv_close_transform (__wcsmbs_gconv_fcts.tomb, 1);
-	  __gconv_close_transform (__wcsmbs_gconv_fcts.towc, 1);
+	  if (__wcsmbs_gconv_fcts.tomb != &to_mb)
+	    __gconv_close_transform (__wcsmbs_gconv_fcts.tomb,
+				     __wcsmbs_gconv_fcts.tomb_nsteps);
+	  if (__wcsmbs_gconv_fcts.towc != &to_wc)
+	    __gconv_close_transform (__wcsmbs_gconv_fcts.towc,
+				     __wcsmbs_gconv_fcts.towc_nsteps);
 
 	  /* Get name of charset of the locale.  */
 	  charset_name = new_category->values[_NL_ITEM_INDEX(CODESET)].string;
@@ -181,9 +203,10 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
 	  /* It is not necessary to use transliteration in this direction
 	     since the internal character set is supposed to be able to
 	     represent all others.  */
-	  new_towc = getfct ("INTERNAL", complete_name);
+	  new_towc = getfct ("INTERNAL", complete_name, &new_towc_nsteps);
 	  new_tomb = (new_towc != NULL
-		      ? getfct (complete_name, "INTERNAL") : NULL);
+		      ? getfct (complete_name, "INTERNAL", &new_tomb_nsteps)
+		      : NULL);
 
 	  /* If any of the conversion functions is not available we don't
 	     use any since this would mean we cannot convert back and
@@ -197,7 +220,9 @@ __wcsmbs_load_conv (const struct locale_data *new_category)
 	    }
 
 	  __wcsmbs_gconv_fcts.tomb = new_tomb;
+	  __wcsmbs_gconv_fcts.tomb_nsteps = new_tomb_nsteps;
 	  __wcsmbs_gconv_fcts.towc = new_towc;
+	  __wcsmbs_gconv_fcts.towc_nsteps = new_towc_nsteps;
 	}
 
       /* Set last-used variable for current locale.  */
@@ -232,27 +257,44 @@ __wcsmbs_clone_conv (struct gconv_fcts *copy)
 }
 
 
-/* Clone the current conversion function set.  */
+/* Get converters for named charset.  */
 int
 internal_function
 __wcsmbs_named_conv (struct gconv_fcts *copy, const char *name)
 {
-  copy->towc = getfct ("INTERNAL", name);
+  copy->towc = getfct ("INTERNAL", name, &copy->towc_nsteps);
   if (copy->towc != NULL)
     {
-      copy->tomb = getfct (name, "INTERNAL");
+      copy->tomb = getfct (name, "INTERNAL", &copy->tomb_nsteps);
       if (copy->tomb == NULL)
-	__gconv_close_transform (copy->towc, 1);
+	__gconv_close_transform (copy->towc, copy->towc_nsteps);
     }
 
-  if (copy->towc == NULL || copy->tomb == NULL)
-    return 1;
+  return copy->towc == NULL || copy->tomb == NULL ? 1 : 0;
+}
 
-  /* Now increment the usage counters.  */
-  if (copy->towc->__shlib_handle != NULL)
-    ++copy->towc->__counter;
-  if (copy->tomb->__shlib_handle != NULL)
-    ++copy->tomb->__counter;
 
-  return 0;
+/* Free all resources if necessary.  */
+static void __attribute__ ((unused))
+free_mem (void)
+{
+  if (__wcsmbs_gconv_fcts.tomb != &to_mb)
+    {
+      struct __gconv_step *old = __wcsmbs_gconv_fcts.tomb;
+      size_t nold = __wcsmbs_gconv_fcts.tomb_nsteps;
+      __wcsmbs_gconv_fcts.tomb = &to_mb;
+      __wcsmbs_gconv_fcts.tomb_nsteps = 1;
+      __gconv_release_cache (old, nold);
+    }
+
+  if (__wcsmbs_gconv_fcts.towc != &to_wc)
+    {
+      struct __gconv_step *old = __wcsmbs_gconv_fcts.towc;
+      size_t nold = __wcsmbs_gconv_fcts.towc_nsteps;
+      __wcsmbs_gconv_fcts.towc = &to_wc;
+      __wcsmbs_gconv_fcts.towc_nsteps = 1;
+      __gconv_release_cache (old, nold);
+    }
 }
+
+text_set_element (__libc_subfreeres, free_mem);
diff --git a/wcsmbs/wcsmbsload.h b/wcsmbs/wcsmbsload.h
index c1bcfe0ea0..6aa6139f77 100644
--- a/wcsmbs/wcsmbsload.h
+++ b/wcsmbs/wcsmbsload.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -26,7 +26,9 @@
 struct gconv_fcts
   {
     struct __gconv_step *towc;
+    size_t towc_nsteps;
     struct __gconv_step *tomb;
+    size_t tomb_nsteps;
   };
 
 /* Set of currently active conversion functions.  */