use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / decompress.c
index b7cd8a6..9dfec88 100644 (file)
@@ -1,5 +1,5 @@
 /* Interface to zlib.
-   Copyright (C) 2013 Free Software Foundation, Inc.
+   Copyright (C) 2013-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -85,7 +85,7 @@ init_zlib_functions (void)
 \f
 struct decompress_unwind_data
 {
-  ptrdiff_t old_point, start;
+  ptrdiff_t old_point, start, nbytes;
   z_stream *stream;
 };
 
@@ -95,12 +95,14 @@ unwind_decompress (void *ddata)
   struct decompress_unwind_data *data = ddata;
   fn_inflateEnd (data->stream);
 
-  /* Delete any uncompressed data already inserted and restore point.  */
+  /* Delete any uncompressed data already inserted on error.  */
   if (data->start)
-    {
-      del_range (data->start, PT);
-      SET_PT (data->old_point);
-    }
+    del_range (data->start, data->start + data->nbytes);
+
+  /* Put point where it was, or if the buffer has shrunk because the
+     compressed data is bigger than the uncompressed, at
+     point-max.  */
+  SET_PT (min (data->old_point, ZV));
 }
 
 DEFUN ("zlib-available-p", Fzlib_available_p, Szlib_available_p, 0, 0, 0,
@@ -114,7 +116,8 @@ DEFUN ("zlib-available-p", Fzlib_available_p, Szlib_available_p, 0, 0, 0,
   else
     {
       Lisp_Object status;
-      status = init_zlib_functions () ? Qt : Qnil;
+      zlib_initialized = init_zlib_functions ();
+      status = zlib_initialized ? Qt : Qnil;
       Vlibrary_cache = Fcons (Fcons (Qzlib_dll, status), Vlibrary_cache);
       return status;
     }
@@ -136,7 +139,7 @@ This function can be called only in unibyte buffers.  */)
   z_stream stream;
   int inflate_status;
   struct decompress_unwind_data unwind_data;
-  ptrdiff_t count = SPECPDL_INDEX ();
+  dynwind_begin ();
 
   validate_region (&start, &end);
 
@@ -146,6 +149,10 @@ This function can be called only in unibyte buffers.  */)
 #ifdef WINDOWSNT
   if (!zlib_initialized)
     zlib_initialized = init_zlib_functions ();
+  if (!zlib_initialized) {
+    dynwind_end ();
+    return Qnil;
+  }
 #endif
 
   /* This is a unibyte buffer, so character positions and bytes are
@@ -160,15 +167,17 @@ This function can be called only in unibyte buffers.  */)
   stream.avail_in = 0;
   stream.next_in = Z_NULL;
 
-  /* The magic number 32 apparently means "autodect both the gzip and
+  /* The magic number 32 apparently means "autodetect both the gzip and
      zlib formats" according to zlib.h.  */
-  if (fn_inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK)
+  if (fn_inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK) {
+    dynwind_end ();
     return Qnil;
+  }
 
   unwind_data.start = iend;
   unwind_data.stream = &stream;
   unwind_data.old_point = PT;
-
+  unwind_data.nbytes = 0;
   record_unwind_protect_ptr (unwind_decompress, &unwind_data);
 
   /* Insert the decompressed data at the end of the compressed data.  */
@@ -181,12 +190,10 @@ This function can be called only in unibyte buffers.  */)
     {
       /* Maximum number of bytes that one 'inflate' call should read and write.
         Do not make avail_out too large, as that might unduly delay C-g.
-        In any case zlib requires that these values not exceed UINT_MAX.  */
+        zlib requires that avail_in and avail_out not exceed UINT_MAX.  */
       ptrdiff_t avail_in = min (iend - pos_byte, UINT_MAX);
-      enum { avail_out = 1 << 14 };
-      verify (avail_out <= UINT_MAX);
-
-      ptrdiff_t decompressed;
+      int avail_out = 16 * 1024;
+      int decompressed;
 
       if (GAP_SIZE < avail_out)
        make_gap (avail_out - GAP_SIZE);
@@ -198,19 +205,24 @@ This function can be called only in unibyte buffers.  */)
       pos_byte += avail_in - stream.avail_in;
       decompressed = avail_out - stream.avail_out;
       insert_from_gap (decompressed, decompressed, 0);
+      unwind_data.nbytes += decompressed;
       QUIT;
     }
   while (inflate_status == Z_OK);
 
-  if (inflate_status != Z_STREAM_END)
-    return unbind_to (count, Qnil);
+  if (inflate_status != Z_STREAM_END){
+    
+      dynwind_end ();
+      return Qnil;
+    }
 
   unwind_data.start = 0;
 
   /* Delete the compressed data.  */
   del_range (istart, iend);
 
-  return unbind_to (count, Qt);
+  dynwind_end ();
+  return Qt;
 }
 
 \f
@@ -220,9 +232,9 @@ This function can be called only in unibyte buffers.  */)
 void
 syms_of_decompress (void)
 {
+#include "decompress.x"
+
   DEFSYM (Qzlib_dll, "zlib");
-  defsubr (&Szlib_decompress_region);
-  defsubr (&Szlib_available_p);
 }
 
 #endif /* HAVE_ZLIB */