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.c202
1 files changed, 118 insertions, 84 deletions
diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c
index 6b9930e50a..24521c0631 100644
--- a/iconv/iconv_prog.c
+++ b/iconv/iconv_prog.c
@@ -36,7 +36,9 @@
 #ifdef _POSIX_MAPPED_FILES
 # include <sys/mman.h>
 #endif
+#include <charmap.h>
 #include <gconv_int.h>
+#include "iconv_prog.h"
 
 /* Get libc version number.  */
 #include "../version.h"
@@ -94,13 +96,13 @@ static const char *to_code;
 static const char *output_file;
 
 /* Nonzero if verbose ouput is wanted.  */
-static int verbose;
+int verbose;
 
 /* Nonzero if list of all coded character sets is wanted.  */
 static int list;
 
 /* If nonzero omit invalid character from output.  */
-static int omit_invalid;
+int omit_invalid;
 
 /* Prototypes for the functions doing the actual work.  */
 static int process_block (iconv_t cd, char *addr, size_t len, FILE *output);
@@ -117,6 +119,8 @@ main (int argc, char *argv[])
   FILE *output;
   iconv_t cd;
   const char *orig_to_code;
+  struct charmap_t *from_charmap = NULL;
+  struct charmap_t *to_charmap = NULL;
 
   /* Set locale via LC_ALL.  */
   setlocale (LC_ALL, "");
@@ -179,18 +183,23 @@ main (int argc, char *argv[])
       to_code = newp;
     }
 
-  /* Let's see whether we have these coded character sets.  */
-  cd = iconv_open (to_code, from_code);
-  if (cd == (iconv_t) -1)
-    {
-      if (errno == EINVAL)
-	error (EXIT_FAILURE, 0,
-	       _("conversion from `%s' to `%s' not supported"),
-	       from_code, orig_to_code);
-      else
-	error (EXIT_FAILURE, errno,
-	       _("failed to start conversion processing"));
-    }
+  /* POSIX 1003.2b introduces a silly thing: the arguments to -t anf -f
+     can be file names of charmaps.  In this case iconv will have to read
+     those charmaps and use them to do the conversion.  But there are
+     holes in the specification.  There is nothing said that if -f is a
+     charmap filename that -t must be, too.  And vice versa.  There is
+     also no word about the symbolic names used.  What if they don't
+     match?  */
+  if (strchr (from_code, '/') != NULL)
+    /* The from-name might be a charmap file name.  Try reading the
+       file.  */
+    from_charmap = charmap_read (from_code, /*0, 1*/1, 0, 0);
+
+  if (strchr (orig_to_code, '/') != NULL)
+    /* The to-name might be a charmap file name.  Try reading the
+       file.  */
+    to_charmap = charmap_read (orig_to_code, /*0, 1,*/1,0, 0);
+
 
   /* Determine output file.  */
   if (output_file != NULL && strcmp (output_file, "-") != 0)
@@ -202,92 +211,117 @@ main (int argc, char *argv[])
   else
     output = stdout;
 
-  /* Now process the remaining files.  Write them to stdout or the file
-     specified with the `-o' parameter.  If we have no file given as
-     the parameter process all from stdin.  */
-  if (remaining == argc)
-    {
-      if (process_file (cd, stdin, output) != 0)
-	status = EXIT_FAILURE;
-    }
+  /* At this point we have to handle two cases.  The first one is
+     where a charmap is used for the from- or to-charset, or both.  We
+     handle this special since it is very different from the sane way of
+     doing things.  The other case allows converting using the iconv()
+     function.  */
+  if (from_charmap != NULL || to_charmap != NULL)
+    /* Construct the conversion table and do the conversion.  */
+    status = charmap_conversion (from_code, from_charmap, to_code, to_charmap,
+				 argc, remaining, argv, output);
   else
-    do
-      {
-	struct stat st;
-	char *addr;
-	int fd;
-
+    {
+      /* Let's see whether we have these coded character sets.  */
+      cd = iconv_open (to_code, from_code);
+      if (cd == (iconv_t) -1)
+	{
+	  if (errno == EINVAL)
+	    error (EXIT_FAILURE, 0,
+		   _("conversion from `%s' to `%s' not supported"),
+		   from_code, orig_to_code);
+	  else
+	    error (EXIT_FAILURE, errno,
+		   _("failed to start conversion processing"));
+	}
 
-	if (verbose)
-	  printf ("%s:\n", argv[remaining]);
-	if (strcmp (argv[remaining], "-") == 0)
-	  fd = 0;
-	else
+      /* Now process the remaining files.  Write them to stdout or the file
+	 specified with the `-o' parameter.  If we have no file given as
+	 the parameter process all from stdin.  */
+      if (remaining == argc)
+	{
+	  if (process_file (cd, stdin, output) != 0)
+	    status = EXIT_FAILURE;
+	}
+      else
+	do
 	  {
-	    fd = open (argv[remaining], O_RDONLY);
-
-	    if (fd == -1)
+	    struct stat st;
+	    char *addr;
+	    int fd;
+
+	    if (verbose)
+	      printf ("%s:\n", argv[remaining]);
+	    if (strcmp (argv[remaining], "-") == 0)
+	      fd = 0;
+	    else
 	      {
-		error (0, errno, _("cannot open input file `%s'"),
-		       argv[remaining]);
-		status = EXIT_FAILURE;
-		continue;
+		fd = open (argv[remaining], O_RDONLY);
+
+		if (fd == -1)
+		  {
+		    error (0, errno, _("cannot open input file `%s'"),
+			   argv[remaining]);
+		    status = EXIT_FAILURE;
+		    continue;
+		  }
 	      }
-	  }
 
 #ifdef _POSIX_MAPPED_FILES
-	/* We have possibilities for reading the input file.  First try
-	   to mmap() it since this will provide the fastest solution.  */
-	if (fstat (fd, &st) == 0
-	    && ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0))
-		!= MAP_FAILED))
-	  {
-	    /* Yes, we can use mmap().  The descriptor is not needed
-               anymore.  */
-	    if (close (fd) != 0)
-	      error (EXIT_FAILURE, errno, _("error while closing input `%s'"),
-		     argv[remaining]);
-
-	    if (process_block (cd, addr, st.st_size, output) < 0)
+	    /* We have possibilities for reading the input file.  First try
+	       to mmap() it since this will provide the fastest solution.  */
+	    if (fstat (fd, &st) == 0
+		&& ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE,
+				  fd, 0)) != MAP_FAILED))
 	      {
-		/* Something went wrong.  */
-		status = EXIT_FAILURE;
+		/* Yes, we can use mmap().  The descriptor is not needed
+		   anymore.  */
+		if (close (fd) != 0)
+		  error (EXIT_FAILURE, errno,
+			 _("error while closing input `%s'"),
+			 argv[remaining]);
+
+		if (process_block (cd, addr, st.st_size, output) < 0)
+		  {
+		    /* Something went wrong.  */
+		    status = EXIT_FAILURE;
+
+		    /* We don't need the input data anymore.  */
+		    munmap ((void *) addr, st.st_size);
+
+		    /* We cannot go on with producing output since it might
+		       lead to problem because the last output might leave
+		       the output stream in an undefined state.  */
+		    break;
+		  }
 
 		/* We don't need the input data anymore.  */
 		munmap ((void *) addr, st.st_size);
-
-		/* We cannot go on with producing output since it might
-		   lead to problem because the last output might leave
-		   the output stream in an undefined state.  */
-		break;
 	      }
-
-	    /* We don't need the input data anymore.  */
-	    munmap ((void *) addr, st.st_size);
-	  }
-	else
+	    else
 #endif	/* _POSIX_MAPPED_FILES */
-	  {
-	    /* Read the file in pieces.  */
-	    if (process_fd (cd, fd, output) != 0)
 	      {
-		/* Something went wrong.  */
-		status = EXIT_FAILURE;
-
-		/* We don't need the input file anymore.  */
+		/* Read the file in pieces.  */
+		if (process_fd (cd, fd, output) != 0)
+		  {
+		    /* Something went wrong.  */
+		    status = EXIT_FAILURE;
+
+		    /* We don't need the input file anymore.  */
+		    close (fd);
+
+		    /* We cannot go on with producing output since it might
+		       lead to problem because the last output might leave
+		       the output stream in an undefined state.  */
+		    break;
+		  }
+
+		/* Now close the file.  */
 		close (fd);
-
-		/* We cannot go on with producing output since it might
-		   lead to problem because the last output might leave
-		   the output stream in an undefined state.  */
-		break;
 	      }
-
-	    /* Now close the file.  */
-	    close (fd);
 	  }
-      }
-    while (++remaining < argc);
+	while (++remaining < argc);
+    }
 
   /* Close the output file now.  */
   if (fclose (output))
@@ -402,7 +436,7 @@ conversion stopped due to problem in writing the output"));
              character sets we have to flush the state now.  */
 	  outptr = outbuf;
 	  outlen = OUTBUF_SIZE;
-	  n = iconv (cd, NULL, NULL, &outptr, &outlen);
+	  (void) iconv (cd, NULL, NULL, &outptr, &outlen);
 
 	  if (outptr != outbuf)
 	    {