diff --git a/ChangeLog b/ChangeLog index 1feddc0a8e2..c0b7d967113 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2013-08-12 Eli Zaretskii + + * configure.ac (HAVE_ZLIB): Don't use -lz on MinGW. + +2013-08-12 Paul Eggert + + Minor zlib configuration tweaks. + * configure.ac (HAVE_ZLIB): Don't assume zlib is linked if PNG is. + +2013-08-12 Eli Zaretskii + + * configure.ac (LIBZ): Comment on w32 peculiarities regarding LIBZ. + 2013-08-12 Paul Eggert Merge from gnulib, incorporating: diff --git a/configure.ac b/configure.ac index 7d433e95201..cae27025311 100644 --- a/configure.ac +++ b/configure.ac @@ -2985,21 +2985,19 @@ AC_SUBST(LIBPNG) HAVE_ZLIB=no LIBZ= if test "${with_zlib}" != "no"; then - if test "${HAVE_PNG}" = "yes"; then - ### PNG depends on zlib, so if we have PNG, we have zlib. - HAVE_ZLIB=yes - else - ### No PNG, so check zlib ourselves. - OLIBS=$LIBS - AC_SEARCH_LIBS([inflateEnd], [z], [HAVE_ZLIB=yes]) - LIBS=$OLIBS - case $ac_cv_search_inflateEnd in - -*) LIBZ=$ac_cv_search_inflateEnd ;; - esac - fi + OLIBS=$LIBS + AC_SEARCH_LIBS([inflateEnd], [z], [HAVE_ZLIB=yes]) + LIBS=$OLIBS + case $ac_cv_search_inflateEnd in + -*) LIBZ=$ac_cv_search_inflateEnd ;; + esac fi if test "${HAVE_ZLIB}" = "yes"; then AC_DEFINE([HAVE_ZLIB], 1, [Define to 1 if you have the zlib library (-lz).]) + ### mingw32 doesn't use -lz, since it loads the library dynamically. + if test "${opsys}" = "mingw32"; then + LIBZ= + fi fi AC_SUBST(LIBZ) diff --git a/etc/NEWS b/etc/NEWS index f5f6e48639e..715f7906073 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -43,7 +43,8 @@ no longer created during installation. ** Emacs can be compiled with zlib support. If this library is present (which it normally is on most systems), the function -`decompress-gzipped-region' becomes available. +`zlib-decompress-region' becomes available, which can decompress gzip- +and zlib-format compressed data. --- ** Emacs for NS (OSX, GNUStep) can be built with ImageMagick support. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1b7aceb5979..290af08f765 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,18 @@ +2013-08-12 Grégoire Jadi + + * mail/sendmail.el (sendmail-send-it): Don't kill the error buffer + if sending fails. This makes debugging easier. + +2013-08-12 Juanma Barranquero + + * xml.el (xml-parse-tag-1): Use looking-at (this reverts change in + 2013-08-11T00:07:48Z!lekktu@gmail.com, which breaks the test suite). + https://lists.gnu.org/archive/html/emacs-devel/2013-08/msg00263.html + +2013-08-12 Eli Zaretskii + + * term/w32-win.el (dynamic-library-alist): Add DLLs for zlib. + 2013-08-12 Glenn Morris * format.el (format-annotate-function): diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el index e1dee3295f2..4fdd75c68a6 100644 --- a/lisp/mail/sendmail.el +++ b/lisp/mail/sendmail.el @@ -1114,6 +1114,7 @@ external program defined by `sendmail-program'." (let ((errbuf (if mail-interactive (generate-new-buffer " sendmail errors") 0)) + (error nil) (tembuf (generate-new-buffer " sendmail temp")) (multibyte enable-multibyte-characters) (case-fold-search nil) @@ -1278,10 +1279,13 @@ external program defined by `sendmail-program'." (exit-value (apply 'call-process-region args))) (cond ((or (null exit-value) (eq 0 exit-value))) ((numberp exit-value) + (setq error t) (error "Sending...failed with exit value %d" exit-value)) ((stringp exit-value) + (setq error t) (error "Sending...terminated by signal: %s" exit-value)) (t + (setq error t) (error "SENDMAIL-SEND-IT -- fall through: %S" exit-value)))) (or fcc-was-found (error "No recipients"))) @@ -1290,12 +1294,15 @@ external program defined by `sendmail-program'." (goto-char (point-min)) (while (re-search-forward "\n\n* *" nil t) (replace-match "; ")) - (if (not (zerop (buffer-size))) - (error "Sending...failed to %s" - (buffer-substring (point-min) (point-max))))))) + (unless (zerop (buffer-size)) + (setq error t) + (error "Sending...failed to %s" + (buffer-substring (point-min) (point-max))))))) (kill-buffer tembuf) - (if (bufferp errbuf) - (kill-buffer errbuf))))) + (if (and (bufferp errbuf) + (not error)) + (kill-buffer errbuf) + (switch-to-buffer-other-window errbuf))))) (autoload 'rmail-output-to-rmail-buffer "rmailout") diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el index acadb0fad43..55181ab7d6d 100644 --- a/lisp/term/w32-win.el +++ b/lisp/term/w32-win.el @@ -229,7 +229,8 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") '(glib "libglib-2.0-0.dll") '(gobject "libgobject-2.0-0.dll") '(gnutls "libgnutls-28.dll" "libgnutls-26.dll") - '(libxml2 "libxml2-2.dll" "libxml2.dll"))) + '(libxml2 "libxml2-2.dll" "libxml2.dll") + '(zlib "zlib1.dll" "libz-1.dll"))) ;;; multi-tty support (defvar w32-initialized nil diff --git a/lisp/url/ChangeLog b/lisp/url/ChangeLog index 9bdaff6f51a..2346803c6bf 100644 --- a/lisp/url/ChangeLog +++ b/lisp/url/ChangeLog @@ -1,3 +1,11 @@ +2013-08-12 Lars Magne Ingebrigtsen + + * url-http.el (url-handle-content-transfer-encoding): Renamed + `zlib-decompress-gzipped-region' and check whether it's available, + too. + (url-handle-content-transfer-encoding): Renamed + `zlib-decompress-region' again. + 2013-08-11 Lars Magne Ingebrigtsen * url-vars.el (url-mime-encoding-string): If we have built-in gzip diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el index beffbe1f79b..07049591cf0 100644 --- a/lisp/url/url-http.el +++ b/lisp/url/url-http.el @@ -860,13 +860,14 @@ should be shown to the user." (defun url-handle-content-transfer-encoding () (let ((encoding (mail-fetch-field "content-encoding"))) (when (and encoding - (fboundp 'decompress-gzipped-region) + (fboundp 'zlib-decompress-region) + (zlib-available-p) (equal (downcase encoding) "gzip")) (save-restriction (widen) (goto-char (point-min)) (when (search-forward "\n\n") - (decompress-gzipped-region (point) (point-max))))))) + (zlib-decompress-region (point) (point-max))))))) ;; Miscellaneous (defun url-http-activate-callback () diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el index a59667b57b0..0361e01dfb4 100644 --- a/lisp/url/url-vars.el +++ b/lisp/url/url-vars.el @@ -210,7 +210,8 @@ Should be an assoc list of headers/contents.") (defvar url-request-method nil "The method to use for the next request.") -(defvar url-mime-encoding-string (and (fboundp 'decompress-gzipped-region) +(defvar url-mime-encoding-string (and (fboundp 'zlib-decompress-region) + (zlib-available-p) "gzip") "String to send in the Accept-encoding: field in HTTP requests.") diff --git a/lisp/xml.el b/lisp/xml.el index e4d5f0b6b6d..b62065eb48f 100644 --- a/lisp/xml.el +++ b/lisp/xml.el @@ -538,7 +538,7 @@ Return one of: (forward-char 1) ;; Now check that we have the right end-tag. (let ((end (concat ""))) - (while (not (looking-at-p end)) + (while (not (looking-at end)) (cond ((eobp) (error "XML: (Not Well-Formed) End of document while reading element `%s'" diff --git a/src/ChangeLog b/src/ChangeLog index 679b82ba63c..04c89b63fa4 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,39 @@ +2013-08-12 Eli Zaretskii + + * decompress.c [WINDOWSNT]: New static variable. + (Fzlib_decompress_region) [WINDOWSNT]: Call init_zlib_functions if + not yet initialized. + +2013-08-12 Lars Magne Ingebrigtsen + + * decompress.c (Fzlib_decompress_region): Support zlib + decompression, too, and rename. + +2013-08-12 Paul Eggert + + Minor zlib configuration tweaks. + * decompress.c (fn_inflateInit2) [!WINDOWSNT]: + Don't assume presence of fn_inflateInit2_ zlib internal function. + +2013-08-12 Lars Magne Ingebrigtsen + + * decompress.c (Fzlib_decompress_gzipped_region): Rename to + include the zlib prefix. + +2013-08-12 Eli Zaretskii + + * decompress.c [WINDOWSNT]: Include windows.h and w32.h. + (DEF_ZLIB_FN, LOAD_ZLIB_FN) [WINDOWSNT]: New macros. Use them to + define static variables that are pointers to zlib functions to be + dynamically loaded. + (init_zlib_functions) [WINDOWSNT]: New function. + (fn_inflateInit2_, fn_inflate, fn_inflateEnd, fn_inflateInit2): + New macros. + (Fdecompress_gzipped_region, unwind_decompress): Use the fn_* + macros instead of invoking the zlib functions directly. + (syms_of_decompress): DEFSYM Qzlib_dll. Staticpro + Szlib_available_p. + 2013-08-12 Dmitry Antipov Avoid looping over all frame windows to freeze and unfreeze. diff --git a/src/decompress.c b/src/decompress.c index 866f4f51516..a09033ab8c3 100644 --- a/src/decompress.c +++ b/src/decompress.c @@ -26,6 +26,60 @@ along with GNU Emacs. If not, see . */ #include "character.h" #include "buffer.h" +static Lisp_Object Qzlib_dll; + +#ifdef WINDOWSNT +#include +#include "w32.h" + +/* Macro for defining functions that will be loaded from the zlib DLL. */ +#define DEF_ZLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args + +/* Macro for loading zlib functions from the library. */ +#define LOAD_ZLIB_FN(lib,func) { \ + fn_##func = (void *) GetProcAddress (lib, #func); \ + if (!fn_##func) return false; \ + } + +DEF_ZLIB_FN (int, inflateInit2_, + (z_streamp strm, int windowBits, const char *version, int stream_size)); + +DEF_ZLIB_FN (int, inflate, + (z_streamp strm, int flush)); + +DEF_ZLIB_FN (int, inflateEnd, + (z_streamp strm)); + +static bool zlib_initialized; + +static bool +init_zlib_functions (void) +{ + HMODULE library = w32_delayed_load (Qzlib_dll); + + if (!library) + { + message1 ("zlib library not found"); + return false; + } + + LOAD_ZLIB_FN (library, inflateInit2_); + LOAD_ZLIB_FN (library, inflate); + LOAD_ZLIB_FN (library, inflateEnd); + return true; +} + +#define fn_inflateInit2(strm, windowBits) \ + fn_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + +#else /* !WINDOWSNT */ + +#define fn_inflateInit2 inflateInit2 +#define fn_inflate inflate +#define fn_inflateEnd inflateEnd + +#endif /* WINDOWSNT */ + struct decompress_unwind_data { @@ -37,7 +91,7 @@ static void unwind_decompress (void *ddata) { struct decompress_unwind_data *data = ddata; - inflateEnd (data->stream); + fn_inflateEnd (data->stream); /* Delete any uncompressed data already inserted and restore point. */ if (data->start) @@ -47,10 +101,30 @@ unwind_decompress (void *ddata) } } -DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region, - Sdecompress_gzipped_region, +DEFUN ("zlib-available-p", Fzlib_available_p, Szlib_available_p, 0, 0, 0, + doc: /* Return t if zlib decompression is available in this instance of Emacs. */) + (void) +{ +#ifdef WINDOWSNT + Lisp_Object found = Fassq (Qzlib_dll, Vlibrary_cache); + if (CONSP (found)) + return XCDR (found); + else + { + Lisp_Object status; + status = init_zlib_functions () ? Qt : Qnil; + Vlibrary_cache = Fcons (Fcons (Qzlib_dll, status), Vlibrary_cache); + return status; + } +#else + return Qt; +#endif +} + +DEFUN ("zlib-decompress-region", Fzlib_decompress_region, + Szlib_decompress_region, 2, 2, 0, - doc: /* Decompress a gzip-compressed region. + doc: /* Decompress a gzip- or zlib-compressed region. Replace the text in the region by the decompressed data. On failure, return nil and leave the data in place. This function can be called only in unibyte buffers. */) @@ -67,6 +141,11 @@ This function can be called only in unibyte buffers. */) if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) error ("This function can be called only in unibyte buffers"); +#ifdef WINDOWSNT + if (!zlib_initialized) + zlib_initialized = init_zlib_functions (); +#endif + /* This is a unibyte buffer, so character positions and bytes are the same. */ istart = XINT (start); @@ -79,8 +158,9 @@ This function can be called only in unibyte buffers. */) stream.avail_in = 0; stream.next_in = Z_NULL; - /* This magic number apparently means "this is gzip". */ - if (inflateInit2 (&stream, 16 + MAX_WBITS) != Z_OK) + /* The magic number 32 apparently means "autodect both the gzip and + zlib formats" according to zlib.h. */ + if (fn_inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK) return Qnil; unwind_data.start = iend; @@ -111,7 +191,7 @@ This function can be called only in unibyte buffers. */) stream.avail_in = avail_in; stream.next_out = GPT_ADDR; stream.avail_out = avail_out; - inflate_status = inflate (&stream, Z_NO_FLUSH); + inflate_status = fn_inflate (&stream, Z_NO_FLUSH); pos_byte += avail_in - stream.avail_in; decompressed = avail_out - stream.avail_out; insert_from_gap (decompressed, decompressed, 0); @@ -137,7 +217,9 @@ This function can be called only in unibyte buffers. */) void syms_of_decompress (void) { - defsubr (&Sdecompress_gzipped_region); + DEFSYM (Qzlib_dll, "zlib"); + defsubr (&Szlib_decompress_region); + defsubr (&Szlib_available_p); } #endif /* HAVE_ZLIB */ diff --git a/test/automated/data/decompress/foo-gzipped b/test/automated/data/decompress/foo-gzipped new file mode 100644 index 00000000000..a68653fcbb9 Binary files /dev/null and b/test/automated/data/decompress/foo-gzipped differ diff --git a/test/automated/zlib-tests.el b/test/automated/zlib-tests.el new file mode 100644 index 00000000000..d03d4c981b8 --- /dev/null +++ b/test/automated/zlib-tests.el @@ -0,0 +1,40 @@ +;;; zlib-tests.el --- Test suite for zlib. + +;; Copyright (C) 2013 Free Software Foundation, Inc. + +;; Author: Lars Ingebrigtsen + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'ert) + +(ert-deftest zlib--decompress () + "Test decompressing a gzipped file." + (when (and (fboundp 'zlib-available-p) + (zlib-available-p)) + (should (string= + (with-temp-buffer + (set-buffer-multibyte nil) + (insert-file-contents-literally "data/decompress/foo-gzipped") + (zlib-decompress-region (point-min) (point-max)) + (buffer-string)) + "foo\n")))) + +(provide 'zlib-tests) + +;;; zlib-tests.el ends here.