about summary refs log tree commit diff
path: root/iconv
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2001-05-22 22:30:18 +0000
committerUlrich Drepper <drepper@redhat.com>2001-05-22 22:30:18 +0000
commit2373b30ea829ad5dd9599b29902c80101deefc78 (patch)
tree79874a0fea3457093e8f2834a2bf7bad41a1863a /iconv
parent25e57b10f3943cefa888ba7f90e57bcda18ed7d8 (diff)
downloadglibc-2373b30ea829ad5dd9599b29902c80101deefc78.tar.gz
glibc-2373b30ea829ad5dd9599b29902c80101deefc78.tar.xz
glibc-2373b30ea829ad5dd9599b29902c80101deefc78.zip
Update.
2001-05-20  Bruno Haible  <haible@clisp.cons.org>

	* iconvdata/cp1255.c: Completely rewritten.
	* iconvdata/Makefile (gen-8bit-gap-modules): Remove cp1255.
	* iconvdata/testdata/WINDOWS-1255: New file.
	* iconvdata/testdata/WINDOWS-1255..UTF8: New file.
	* iconvdata/TESTS: Add WINDOWS-1255 test.
	* iconvdata/CP1255.irreversible: New file.

2001-05-20  Bruno Haible  <haible@clisp.cons.org>

	* iconvdata/cp1258.c: Completely rewritten.
	* iconvdata/Makefile (gen-8bit-gap-modules): Remove cp1258.
	* iconvdata/testdata/WINDOWS-1258: New file.
	* iconvdata/testdata/WINDOWS-1258..UTF8: New file.
	* iconvdata/TESTS: Add WINDOWS-1258 test.
	* iconvdata/tst-table-from.c (try): Reset the iconv descriptor before
	the main call, and flush it afterwards.
	(utf8_decode): Return a string, possibly containing several Unicode
	characters.
	(main): Update all utf8_decode calls.
	* iconvdata/CP1258.irreversible: New file.

2001-05-20  Bruno Haible  <haible@clisp.cons.org>

	* iconv/gconv.c (__gconv): For flush without output, pass do_flush = 2.
	* iconv/skeleton.c: Distinguish do_flush = 1 and do_flush = 2. In the
	first case, set outbuf, outstart, outend, and call PREPARE_LOOP before
	EMIT_SHIFT_TO_INIT; then pass the output produced by this step down to
	the next step. In the second case, clear the state without calling
	EMIT_SHIFT_TO_INIT.
	* iconvdata/ibm930.c (EMIT_SHIFT_TO_INIT): Use outbuf instead of
	data->__outbuf, and outend instead of data->__outbufend.
	* iconvdata/ibm933.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/ibm935.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/ibm937.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/ibm939.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/iso-2022-cn.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/iso-2022-cn-ext.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/iso-2022-jp.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/iso-2022-kr.c (EMIT_SHIFT_TO_INIT): Likewise.
	* iconvdata/utf-7.c (EMIT_SHIFT_TO_INIT): Likewise.

2001-05-21  Jakub Jelinek  <jakub@redhat.com>

	* elf/rtld.c (dl_main): Compute l_map_end for the main program.
	* elf/dl-sym.c (_dl_sym): Don't check for l_addr == 0.
	If match == _dl_loaded, caller can still come from the main program.
	(_dl_vsym): Likewise.
	* elf/dl-open.c (dl_open_worker): Don't check for l_addr == 0.
	* elf/dl-error.c (_dl_signal_error): Change NULL objname into "".
	* elf/restest2.c: New test.
	* elf/Makefile (tests): Add restest2.
	(restest2, LDFLAGS-restest2): Add rules.
Diffstat (limited to 'iconv')
-rw-r--r--iconv/gconv.c3
-rw-r--r--iconv/skeleton.c101
2 files changed, 85 insertions, 19 deletions
diff --git a/iconv/gconv.c b/iconv/gconv.c
index 7cb78694e0..6a7424bcbf 100644
--- a/iconv/gconv.c
+++ b/iconv/gconv.c
@@ -49,7 +49,8 @@ __gconv (__gconv_t cd, const unsigned char **inbuf,
     /* We just flush.  */
     result = DL_CALL_FCT (cd->__steps->__fct,
 			  (cd->__steps, cd->__data, NULL, NULL, NULL,
-			   irreversible, 1, 0));
+			   irreversible,
+			   cd->__data[last_step].__outbuf == NULL ? 2 : 1, 0));
   else
     {
       const unsigned char *last_start;
diff --git a/iconv/skeleton.c b/iconv/skeleton.c
index 98abc33f6d..bd8b4fe4a2 100644
--- a/iconv/skeleton.c
+++ b/iconv/skeleton.c
@@ -298,28 +298,93 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
      dropped.  */
   if (__builtin_expect (do_flush, 0))
     {
-      status = __GCONV_OK;
-
       /* This should never happen during error handling.  */
       assert (outbufstart == NULL);
 
+      status = __GCONV_OK;
+
 #ifdef EMIT_SHIFT_TO_INIT
-      /* Emit the escape sequence to reset the state.  */
-      EMIT_SHIFT_TO_INIT;
-#else
-      /* Clear the state object.  There might be bytes in there from
-	 previous calls with CONSUME_INCOMPLETE == 1.  */
-      memset (data->__statep, '\0', sizeof (*data->__statep));
+      if (do_flush == 1)
+	{
+	  /* We preserve the initial values of the pointer variables.  */
+	  unsigned char *outbuf = data->__outbuf;
+	  unsigned char *outstart = outbuf;
+	  unsigned char *outend = data->__outbufend;
+
+# ifdef PREPARE_LOOP
+	  PREPARE_LOOP
+# endif
+
+# ifdef SAVE_RESET_STATE
+	  SAVE_RESET_STATE (1);
+# endif
+
+	  /* Emit the escape sequence to reset the state.  */
+	  EMIT_SHIFT_TO_INIT;
+
+	  /* Call the steps down the chain if there are any but only if we
+	     successfully emitted the escape sequence.  This should only
+	     fail if the output buffer is full.  If the input is invalid
+	     it should be discarded since the user wants to start from a
+	     clean state.  */
+	  if (status == __GCONV_OK)
+	    {
+	      if (data->__flags & __GCONV_IS_LAST)
+		/* Store information about how many bytes are available.  */
+		data->__outbuf = outbuf;
+	      else
+		{
+		  /* Write out all output which was produced.  */
+		  if (outbuf > outstart)
+		    {
+		      const unsigned char *outerr = outstart;
+		      int result;
+
+		      result = DL_CALL_FCT (fct, (next_step, next_data,
+						  &outerr, outbuf, NULL,
+						  irreversible, 0,
+						  consume_incomplete));
+
+		      if (result != __GCONV_EMPTY_INPUT)
+			{
+			  if (__builtin_expect (outerr != outbuf, 0))
+			    {
+			      /* We have a problem.  Undo the conversion.  */
+			      outbuf = outstart;
+
+			      /* Restore the state.  */
+# ifdef SAVE_RESET_STATE
+			      SAVE_RESET_STATE (0);
+# endif
+			    }
+
+			  /* Change the status.  */
+			  status = result;
+			}
+		    }
+
+		  if (status == __GCONV_OK)
+		    /* Now flush the remaining steps.  */
+		    status = DL_CALL_FCT (fct, (next_step, next_data, NULL,
+						NULL, NULL, irreversible, 1,
+						consume_incomplete));
+		}
+	    }
+	}
+      else
 #endif
-      /* Call the steps down the chain if there are any but only if we
-         successfully emitted the escape sequence.  This should only
-	 fail if the output buffer is full.  If the input is invalid
-	 it should be discarded since the user wants to start from a
-	 clean slate.  */
-      if (status == __GCONV_OK && ! (data->__flags & __GCONV_IS_LAST))
-	status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL,
-				    NULL, irreversible, 1,
-				    consume_incomplete));
+	{
+	  /* Clear the state object.  There might be bytes in there from
+	     previous calls with CONSUME_INCOMPLETE == 1.  But don't emit
+	     escape sequences.  */
+	  memset (data->__statep, '\0', sizeof (*data->__statep));
+
+	  if (! (data->__flags & __GCONV_IS_LAST))
+	    /* Now flush the remaining steps.  */
+	    status = DL_CALL_FCT (fct, (next_step, next_data, NULL, NULL,
+					NULL, irreversible, do_flush,
+					consume_incomplete));
+	}
     }
   else
     {
@@ -499,7 +564,7 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
 		      *inptrp = inptr;
 		      outbuf = outstart;
 
-		      /* Reset the state.  */
+		      /* Restore the state.  */
 # ifdef SAVE_RESET_STATE
 		      SAVE_RESET_STATE (0);
 # endif