Regenerate tree using Autoconf 2.64 and Automake 1.11.
[deliverable/binutils-gdb.git] / gdb / charset.c
index 3c56613effa03309fd36c6d21fd50b2d640dd151..a59d9c65d33979bf053f91f0903f642ac25455aa 100644 (file)
@@ -22,6 +22,7 @@
 #include "gdbcmd.h"
 #include "gdb_assert.h"
 #include "gdb_obstack.h"
+#include "gdb_wait.h"
 #include "charset-list.h"
 #include "vec.h"
 
 #undef ICONV_CONST
 #define ICONV_CONST const
 
+/* Some systems don't have EILSEQ, so we define it here, but not as
+   EINVAL, because callers of `iconv' want to distinguish EINVAL and
+   EILSEQ.  This is what iconv.h from libiconv does as well.  Note
+   that wchar.h may also define EILSEQ, so this needs to be after we
+   include wchar.h, which happens in defs.h through gdb_wchar.h.  */
+#ifndef EILSEQ
+#define EILSEQ ENOENT
+#endif
+
 iconv_t
 iconv_open (const char *to, const char *from)
 {
@@ -348,9 +358,9 @@ target_charset (void)
 }
 
 const char *
-target_wide_charset (void)
+target_wide_charset (enum bfd_endian byte_order)
 {
-  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+  if (byte_order == BFD_ENDIAN_BIG)
     {
       if (target_wide_charset_be_name)
        return target_wide_charset_be_name;
@@ -527,7 +537,7 @@ make_wchar_iterator (const gdb_byte *input, size_t bytes, const char *charset,
   struct wchar_iterator *result;
   iconv_t desc;
 
-  desc = iconv_open ("wchar_t", charset);
+  desc = iconv_open (INTERMEDIATE_ENCODING, charset);
   if (desc == (iconv_t) -1)
     perror_with_name ("Converting character sets");
 
@@ -664,7 +674,13 @@ find_charset_names (void)
 }
 
 #else /* PHONY_ICONV */
-#ifdef HAVE_ICONVLIST
+
+/* Sometimes, libiconv redefines iconvlist as libiconvlist -- but
+   provides different symbols in the static and dynamic libraries.
+   So, configure may see libiconvlist but not iconvlist.  But, calling
+   iconvlist is the right thing to do and will work.  Hence we do a
+   check here but unconditionally call iconvlist below.  */
+#if defined (HAVE_ICONVLIST) || defined (HAVE_LIBICONVLIST)
 
 /* A helper function that adds some character sets to the vector of
    all character sets.  This is a callback function for iconvlist.  */
@@ -692,38 +708,95 @@ find_charset_names (void)
 static void
 find_charset_names (void)
 {
-  FILE *in;
+  struct pex_obj *child;
+  char *args[3];
+  int err, status;
+  int fail = 1;
+
+  child = pex_init (0, "iconv", NULL);
+
+  args[0] = "iconv";
+  args[1] = "-l";
+  args[2] = NULL;
+  /* Note that we simply ignore errors here.  */
+  if (!pex_run (child, PEX_SEARCH | PEX_STDERR_TO_STDOUT, "iconv",
+               args, NULL, NULL, &err))
+    {
+      FILE *in = pex_read_output (child, 0);
 
-  in = popen ("iconv -l", "r");
-  /* It is ok to ignore errors; we'll fall back on a default.  */
-  if (!in)
-    return;
+      /* POSIX says that iconv -l uses an unspecified format.  We
+        parse the glibc and libiconv formats; feel free to add others
+        as needed.  */
+      while (!feof (in))
+       {
+         /* The size of buf is chosen arbitrarily.  */
+         char buf[1024];
+         char *start, *r;
+         int len, keep_going;
+
+         r = fgets (buf, sizeof (buf), in);
+         if (!r)
+           break;
+         len = strlen (r);
+         if (len <= 3)
+           continue;
+         /* Strip off the newline.  */
+         --len;
+         /* Strip off one or two '/'s.  glibc will print lines like
+            "8859_7//", but also "10646-1:1993/UCS4/".  */
+         if (buf[len - 1] == '/')
+           --len;
+         if (buf[len - 1] == '/')
+           --len;
+         buf[len] = '\0';
+
+         /* libiconv will print multiple entries per line, separated
+            by spaces.  */
+         start = buf;
+         while (1)
+           {
+             int keep_going;
+             char *p;
+
+             /* Find the next space, or end-of-line.  */
+             for (p = start; *p && *p != ' '; ++p)
+               ;
+             /* Ignore an empty result.  */
+             if (p == start)
+               break;
+             keep_going = *p;
+             *p = '\0';
+             VEC_safe_push (char_ptr, charsets, xstrdup (start));
+             if (!keep_going)
+               break;
+             /* Skip any extra spaces.  */
+             for (start = p + 1; *start && *start == ' '; ++start)
+               ;
+           }
+       }
+
+      if (pex_get_status (child, 1, &status)
+         && WIFEXITED (status) && !WEXITSTATUS (status))
+       fail = 0;
 
-  /* POSIX says that iconv -l uses an unspecified format.  We parse
-     the glibc format; feel free to add others as needed.  */
-  while (!feof (in))
-    {
-      /* The size of buf is chosen arbitrarily.  A character set name
-        longer than this would not be very nice.  */
-      char buf[80];
-      int len;
-      char *r = fgets (buf, sizeof (buf), in);
-      if (!r)
-       break;
-      len = strlen (r);
-      if (len <= 3)
-       continue;
-      if (buf[len - 2] == '/' && buf[len - 3] == '/')
-       buf[len - 3] = '\0';
-      VEC_safe_push (char_ptr, charsets, xstrdup (buf));
     }
 
-  pclose (in);
+  pex_free (child);
 
-  VEC_safe_push (char_ptr, charsets, NULL);
+  if (fail)
+    {
+      /* Some error occurred, so drop the vector.  */
+      int ix;
+      char *elt;
+      for (ix = 0; VEC_iterate (char_ptr, charsets, ix, elt); ++ix)
+       xfree (elt);
+      VEC_truncate (char_ptr, charsets, 0);
+    }
+  else
+    VEC_safe_push (char_ptr, charsets, NULL);
 }
 
-#endif /* HAVE_ICONVLIST */
+#endif /* HAVE_ICONVLIST || HAVE_LIBICONVLIST */
 #endif /* PHONY_ICONV */
 
 void
@@ -733,7 +806,7 @@ _initialize_charset (void)
 
   /* The first element is always "auto"; then we skip it for the
      commands where it is not allowed.  */
-  VEC_safe_push (char_ptr, charsets, "auto");
+  VEC_safe_push (char_ptr, charsets, xstrdup ("auto"));
   find_charset_names ();
 
   if (VEC_length (char_ptr, charsets) > 1)
@@ -744,6 +817,10 @@ _initialize_charset (void)
 #ifndef PHONY_ICONV
 #ifdef HAVE_LANGINFO_CODESET
   auto_host_charset_name = nl_langinfo (CODESET);
+  /* Solaris will return `646' here -- but the Solaris iconv then
+     does not accept this.  */
+  if (!strcmp (auto_host_charset_name, "646"))
+    auto_host_charset_name = "ASCII";
   target_charset_name = auto_host_charset_name;
 
   set_be_le_names ();
This page took 0.075915 seconds and 4 git commands to generate.