about summary refs log tree commit diff
path: root/iconv/iconv_prog.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconv/iconv_prog.c')
-rw-r--r--iconv/iconv_prog.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c
index 00b4b95672..e71f8d7369 100644
--- a/iconv/iconv_prog.c
+++ b/iconv/iconv_prog.c
@@ -39,6 +39,7 @@
 #include <charmap.h>
 #include <gconv_int.h>
 #include "iconv_prog.h"
+#include "iconvconfig.h"
 
 /* Get libc version number.  */
 #include "../version.h"
@@ -46,6 +47,9 @@
 #define PACKAGE _libc_intl_domainname
 
 
+/* Defined in gconv_cache.c.  */
+extern void *__gconv_cache;
+
 /* Name and version of program.  */
 static void print_version (FILE *stream, struct argp_state *state);
 void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
@@ -653,7 +657,7 @@ add_known_names (struct gconv_module *node)
       if (strcmp (node->from_string, "INTERNAL"))
 	tsearch (node->from_string, &printlist,
 		 (__compar_fn_t) strverscmp);
-      if (strcmp (node->to_string, "INTERNAL"))
+      if (strcmp (node->to_string, "INTERNAL") != 0)
 	tsearch (node->to_string, &printlist, (__compar_fn_t) strverscmp);
 
       node = node->same;
@@ -661,6 +665,31 @@ add_known_names (struct gconv_module *node)
   while (node != NULL);
 }
 
+
+static void
+insert_cache (void)
+{
+  const struct gconvcache_header *header;
+  const char *strtab;
+  const struct hash_entry *hashtab;
+  size_t cnt;
+
+  header = (const struct gconvcache_header *) __gconv_cache;
+  strtab = (char *) __gconv_cache + header->string_offset;
+  hashtab = (struct hash_entry *) ((char *) __gconv_cache
+				   + header->hash_offset);
+
+  for (cnt = 0; cnt < header->hash_size; ++cnt)
+    if (hashtab[cnt].string_offset != 0)
+      {
+	const char *str = strtab + hashtab[cnt].string_offset;
+
+	if (strcmp (str, "INTERNAL") != 0)
+	  tsearch (str, &printlist, (__compar_fn_t) strverscmp);
+      }
+}
+
+
 static void
 internal_function
 print_known_names (void)
@@ -671,11 +700,20 @@ print_known_names (void)
   h = iconv_open ("L1", "L1");
   iconv_close (h);
 
-  /* First add the aliases.  */
-  twalk (__gconv_alias_db, insert_print_list);
+  /* See whether we have a cache.  */
+  if (__gconv_cache != NULL)
+    /* Yep, use only this information.  */
+    insert_cache ();
+  else
+    {
+      /* No, then use the information read from the gconv-modules file.
+	 First add the aliases.  */
+      twalk (__gconv_alias_db, insert_print_list);
 
-  /* Add the from- and to-names from the known modules.  */
-  add_known_names (__gconv_modules_db);
+      /* Add the from- and to-names from the known modules.  */
+      if (__gconv_modules_db != NULL)
+	add_known_names (__gconv_modules_db);
+    }
 
   fputs (_("\
 The following list contain all the coded character sets known.  This does\n\