all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Fabrice Popineau <fabrice.popineau@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: "Óscar Fuentes" <ofv@wanadoo.es>,
	"Juanma Barranquero" <lekktu@gmail.com>,
	"Emacs developers" <emacs-devel@gnu.org>
Subject: Re: 64-bit build on Windows
Date: Sat, 21 Jan 2017 21:40:44 +0100	[thread overview]
Message-ID: <CAFgFV9PbyVqoi1O1EGByAo-BQt_Jd-cK_exn-BqUTVd1WYh73w@mail.gmail.com> (raw)
In-Reply-To: <838tq45gsk.fsf@gnu.org>


[-- Attachment #1.1: Type: text/plain, Size: 1623 bytes --]

2017-01-21 20:55 GMT+01:00 Eli Zaretskii <eliz@gnu.org>:

> > From: Fabrice Popineau <fabrice.popineau@gmail.com>
> > Date: Sat, 21 Jan 2017 20:23:29 +0100
> > Cc: Eli Zaretskii <eliz@gnu.org>, Óscar Fuentes <ofv@wanadoo.es>,
> >       Emacs developers <emacs-devel@gnu.org>
> >
> >  If Emacs on Windows is built to use the DLLs, and they are not
> available (let's say you downloaded a
> >  binary tarball built with Imagemagick support, but you don't have the
> DLLs in your system), Windows
> >  won't allow emacs.exe to run. That's a big problem.
> >
> > ???
> >
> > Not when you use LoadLibrary and fortunately.
>
> The coe that uses LoadLibrary is based on dynamic-library-alist, so as
> long as Imagemagick DLLs are not in that alist, there's no LoadLibrary
> to load them.
>
> >  > What happens if the jpeg or xpm or png dlls are not found ?
> >
> >  Nothing, because they are not statically linked. If Emacs was built
> with jpeg support (or png, etc.), it will
> >  check at runtime (and on demand, the first time a jpeg function is
> needed) that the jpeg DLL can be
> >  loaded. If not, the function will fail and Emacs will take note that
> the DLL is unavailable.
> >
> > And it is the same for ImageMagick.
>
> Please describe how this would work, without using
> dynamic-library-alist.
>

But I never said that it would work without using dynamic-library-alist ?
I said that I may have missed that part of the patch when I have posted it.
I was objecting to the fact that IM has to be statically linked.

The attached patch should be a proof of concept.

Fabrice

[-- Attachment #1.2: Type: text/html, Size: 2447 bytes --]

[-- Attachment #2: master-imagemagick.diff --]
[-- Type: text/plain, Size: 13983 bytes --]

diff --git a/configure.ac b/configure.ac
index dcba7eb..53a2d27 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2462,7 +2461,7 @@ AC_DEFUN
   if test "${with_imagemagick}" != "no"; then
     ## 6.3.5 is the earliest version known to work; see Bug#17339.
     ## 6.8.2 makes Emacs crash; see Bug#13867.
-    IMAGEMAGICK_MODULE="Wand >= 6.3.5 Wand != 6.8.2"
+    IMAGEMAGICK_MODULE="MagickWand >= 6.3.5 MagickWand != 6.8.2"
     EMACS_CHECK_MODULES([IMAGEMAGICK], [$IMAGEMAGICK_MODULE])
     AC_SUBST(IMAGEMAGICK_CFLAGS)
     AC_SUBST(IMAGEMAGICK_LIBS)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index ecb7284..6921ed8 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -280,6 +280,7 @@
       (load "term/w32-win")
       (load "disp-table")
       (when (eq system-type 'windows-nt)
+        (load "image")
         (load "w32-fns")
         (load "ls-lisp")
         (load "dos-w32"))))
diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el
index fda9388..d168e11 100644
--- a/lisp/term/w32-win.el
+++ b/lisp/term/w32-win.el
@@ -271,6 +271,8 @@ libgnutls-version
        '(gdk-pixbuf "libgdk_pixbuf-2.0-0.dll")
        '(glib "libglib-2.0-0.dll")
        '(gobject "libgobject-2.0-0.dll")
+       '(magickwand "libMagickWand-7.Q16HDRI-0.dll" "libMagickWand-7.Q16-0.dll")
+       '(magickcore "libMagickCore-7.Q16HDRI-0.dll" "libMagickCore-7.Q16-0.dll")
        (if (>= libgnutls-version 30400)
            '(gnutls "libgnutls-30.dll")
          '(gnutls "libgnutls-28.dll" "libgnutls-26.dll"))
diff --git a/src/image.c b/src/image.c
index 39677d2..04480f3 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2307,7 +2403,7 @@ x_find_image_fd (Lisp_Object file, int *pfd)
              happens, e.g., under Auto Image File Mode.)  'openp'
              didn't open the file, so we should, because the caller
              expects that.  */
-	  fd = emacs_open (SSDATA (file_found), O_RDONLY, 0);
+          fd = emacs_open (SSDATA (file_found), O_RDONLY | O_BINARY, 0);
 	}
     }
   else	/* fd < 0, but not -2 */
@@ -8244,16 +8382,227 @@ imagemagick_image_p (Lisp_Object object)
 /* The GIF library also defines DrawRectangle, but its never used in Emacs.
    Therefore rename the function so it doesn't collide with ImageMagick.  */
 #define DrawRectangle DrawRectangleGif
+#ifdef __MINGW64__
+#include <ImageMagick-7/MagickWand/MagickWand.h>
+#else
 #include <wand/MagickWand.h>
+#endif
 
 /* ImageMagick 6.5.3 through 6.6.5 hid PixelGetMagickColor for some reason.
    Emacs seems to work fine with the hidden version, so unhide it.  */
+#ifdef __MINGW64__
+#include <ImageMagick-7/MagickCore/version.h>
+#else
 #include <magick/version.h>
+#endif
 #if 0x653 <= MagickLibVersion && MagickLibVersion <= 0x665
 extern WandExport void PixelGetMagickColor (const PixelWand *,
                                             MagickPixelPacket *);
 #endif
 
+#ifdef WINDOWSNT
+DEF_DLL_FN (MagickWand *, CloneMagickWand, (const MagickWand *));
+DEF_DLL_FN (MagickWand *, DestroyMagickWand, (MagickWand *));
+DEF_DLL_FN (MagickWand *, DestroyPixelIterator, (PixelIterator *));
+DEF_DLL_FN (PixelWand *, DestroyPixelWand, (PixelWand *));
+DEF_DLL_FN (MagickBooleanType, MagickCropImage, (MagickWand *, const size_t, const size_t, const ssize_t, const ssize_t));
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+DEF_DLL_FN (MagickBooleanType, MagickExportImagePixels, (MagickWand *, const ssize_t, const ssize_t, const size_t, const size_t, const char *, const StorageType, void *));
+#endif
+DEF_DLL_FN (char *, MagickGetException, (const MagickWand *, ExceptionType *));
+DEF_DLL_FN (MagickWand *, MagickGetImage, (MagickWand *));
+DEF_DLL_FN (DisposeType, MagickGetImageDelay, (MagickWand *));
+DEF_DLL_FN (DisposeType, MagickGetImageDispose, (MagickWand *));
+DEF_DLL_FN (size_t, MagickGetImageHeight, (MagickWand *));
+DEF_DLL_FN (MagickBooleanType, MagickGetImagePage, (MagickWand *, size_t *, size_t *, ssize_t *, ssize_t *));
+DEF_DLL_FN (char *, MagickGetImageSignature, (MagickWand *));
+DEF_DLL_FN (size_t, MagickGetImageWidth, (MagickWand *));
+DEF_DLL_FN (size_t, MagickGetNumberImages, (MagickWand *));
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS
+DEF_DLL_FN (MagickWand *, MagickMergeImageLayers, (MagickWand *, const ImageLayerMethod));
+#else
+DEF_DLL_FN (MagickWand *, MagickFlattenImages, (MagickWand *));
+#endif
+DEF_DLL_FN (MagickBooleanType, MagickReadImage, (MagickWand *, const char *));
+DEF_DLL_FN (MagickBooleanType, MagickReadImageBlob, (MagickWand *, const void *, const size_t));
+DEF_DLL_FN (void *, MagickRelinquishMemory, (void *));
+DEF_DLL_FN (MagickBooleanType, MagickRotateImage, (MagickWand *, const PixelWand *, const double));
+DEF_DLL_FN (MagickBooleanType, MagickScaleImage, (MagickWand *, const size_t, const size_t));
+DEF_DLL_FN (MagickBooleanType, MagickSetFilename, (MagickWand *, const char *));
+DEF_DLL_FN (MagickBooleanType, MagickSetImageBackgroundColor, (MagickWand *, const PixelWand *));
+DEF_DLL_FN (MagickBooleanType, MagickSetIteratorIndex, (MagickWand *, const ssize_t));
+DEF_DLL_FN (void, MagickWandGenesis, (void));
+DEF_DLL_FN (void, MagickWandTerminus, (void));
+DEF_DLL_FN (MagickWand *, NewMagickWand, (void));
+DEF_DLL_FN (PixelIterator *, NewPixelIterator, (MagickWand *));
+DEF_DLL_FN (PixelWand *, NewPixelWand, (void));
+DEF_DLL_FN (double, PixelGetAlpha, (const PixelWand *));
+DEF_DLL_FN (void, PixelGetMagickColor, (const PixelWand *, PixelInfo *));
+DEF_DLL_FN (PixelWand **, PixelGetNextIteratorRow, (PixelIterator *, size_t *));
+DEF_DLL_FN (MagickBooleanType, PixelSetIteratorRow, (PixelIterator *, const ssize_t));
+DEF_DLL_FN (void, PixelSetPixelColor, (PixelWand *, const PixelInfo *));
+DEF_DLL_FN (void, PixelSetRed, (PixelWand *, const double));
+DEF_DLL_FN (void, PixelSetGreen, (PixelWand *, const double));
+DEF_DLL_FN (void, PixelSetBlue, (PixelWand *, const double));
+DEF_DLL_FN (MagickBooleanType, PixelSyncIterator, (PixelIterator *));
+
+DEF_DLL_FN (ExceptionInfo *, DestroyExceptionInfo, (ExceptionInfo *));
+DEF_DLL_FN (char *, DestroyString, (char *));
+DEF_DLL_FN (ExceptionInfo *, AcquireExceptionInfo, ());
+DEF_DLL_FN (char **, GetMagickList, (const char *, size_t *, ExceptionInfo *));
+
+static bool
+init_imagemagick_functions (void)
+{
+  HMODULE magickwand, magickcore;
+
+  if (!(magickcore = w32_delayed_load (Qmagickcore))
+      || !(magickwand = w32_delayed_load (Qmagickwand)))
+    return 0;
+
+  LOAD_DLL_FN (magickwand, CloneMagickWand);
+  LOAD_DLL_FN (magickwand, DestroyMagickWand);
+  LOAD_DLL_FN (magickwand, DestroyPixelIterator);
+  LOAD_DLL_FN (magickwand, DestroyPixelWand);
+  LOAD_DLL_FN (magickwand, MagickCropImage);
+#ifdef HAVE_MAGICKEXPORTIMAGEPIXELS
+  LOAD_DLL_FN (magickwand, MagickExportImagePixels);
+#endif
+  LOAD_DLL_FN (magickwand, MagickGetException);
+  LOAD_DLL_FN (magickwand, MagickGetImage);
+  LOAD_DLL_FN (magickwand, MagickGetImageDelay);
+  LOAD_DLL_FN (magickwand, MagickGetImageDispose);
+  LOAD_DLL_FN (magickwand, MagickGetImageHeight);
+  LOAD_DLL_FN (magickwand, MagickGetImagePage);
+  LOAD_DLL_FN (magickwand, MagickGetImageSignature);
+  LOAD_DLL_FN (magickwand, MagickGetImageWidth);
+  LOAD_DLL_FN (magickwand, MagickGetNumberImages);
+#ifdef HAVE_MAGICKMERGEIMAGELAYERS
+  LOAD_DLL_FN (magickwand, MagickMergeImageLayers);
+#else
+  LOAD_DLL_FN (magickwand, MagickFlattenImages);
+#endif
+  LOAD_DLL_FN (magickwand, MagickReadImage);
+  LOAD_DLL_FN (magickwand, MagickReadImageBlob);
+  LOAD_DLL_FN (magickwand, MagickRelinquishMemory);
+  LOAD_DLL_FN (magickwand, MagickRotateImage);
+  LOAD_DLL_FN (magickwand, MagickScaleImage);
+  LOAD_DLL_FN (magickwand, MagickSetFilename);
+  LOAD_DLL_FN (magickwand, MagickSetImageBackgroundColor);
+  LOAD_DLL_FN (magickwand, MagickSetIteratorIndex);
+  LOAD_DLL_FN (magickwand, MagickWandGenesis);
+  LOAD_DLL_FN (magickwand, MagickWandTerminus);
+  LOAD_DLL_FN (magickwand, NewMagickWand);
+  LOAD_DLL_FN (magickwand, NewPixelIterator);
+  LOAD_DLL_FN (magickwand, NewPixelWand);
+  LOAD_DLL_FN (magickwand, PixelGetAlpha);
+  LOAD_DLL_FN (magickwand, PixelGetMagickColor);
+  LOAD_DLL_FN (magickwand, PixelGetNextIteratorRow);
+  LOAD_DLL_FN (magickwand, PixelSetIteratorRow);
+  LOAD_DLL_FN (magickwand, PixelSetPixelColor);
+  LOAD_DLL_FN (magickwand, PixelSetRed);
+  LOAD_DLL_FN (magickwand, PixelSetGreen);
+  LOAD_DLL_FN (magickwand, PixelSetBlue);
+  LOAD_DLL_FN (magickwand, PixelSyncIterator);
+
+  LOAD_DLL_FN (magickcore, DestroyExceptionInfo);
+  LOAD_DLL_FN (magickcore, DestroyString);
+  LOAD_DLL_FN (magickcore, AcquireExceptionInfo);
+  LOAD_DLL_FN (magickcore, GetMagickList);
+
+  return 1;
+}
+
+#undef CloneMagickWand
+#undef DestroyMagickWand
+#undef DestroyPixelIterator
+#undef DestroyPixelWand
+#undef MagickCropImage
+#undef MagickExportImagePixels
+#undef MagickGetException
+#undef MagickGetImage
+#undef MagickGetImageDelay
+#undef MagickGetImageDispose
+#undef MagickGetImageHeight
+#undef MagickGetImagePage
+#undef MagickGetImageSignature
+#undef MagickGetImageWidth
+#undef MagickGetNumberImages
+#undef MagickMergeImageLayers
+#undef MagickFlattenImages
+#undef MagickReadImage
+#undef MagickReadImageBlob
+#undef MagickRelinquishMemory
+#undef MagickRotateImage
+#undef MagickScaleImage
+#undef MagickSetFilename
+#undef MagickSetImageBackgroundColor
+#undef MagickSetIteratorIndex
+#undef MagickWandGenesis
+#undef MagickWandTerminus
+#undef NewMagickWand
+#undef NewPixelIterator
+#undef NewPixelWand
+#undef PixelGetAlpha
+#undef PixelGetMagickColor
+#undef PixelGetNextIteratorRow
+#undef PixelSetIteratorRow
+#undef PixelSetPixelColor
+#undef PixelSetRed
+#undef PixelSetGreen
+#undef PixelSetBlue
+#undef PixelSyncIterator
+#undef DestroyExceptionInfo
+#undef DestroyString
+#undef AcquireExceptionInfo
+#undef GetMagickList
+
+#define CloneMagickWand fn_CloneMagickWand
+#define DestroyMagickWand fn_DestroyMagickWand
+#define DestroyPixelIterator fn_DestroyPixelIterator
+#define DestroyPixelWand fn_DestroyPixelWand
+#define MagickCropImage fn_MagickCropImage
+#define MagickExportImagePixels fn_MagickExportImagePixels
+#define MagickGetException fn_MagickGetException
+#define MagickGetImage fn_MagickGetImage
+#define MagickGetImageDelay fn_MagickGetImageDelay
+#define MagickGetImageDispose fn_MagickGetImageDispose
+#define MagickGetImageHeight fn_MagickGetImageHeight
+#define MagickGetImagePage fn_MagickGetImagePage
+#define MagickGetImageSignature fn_MagickGetImageSignature
+#define MagickGetImageWidth fn_MagickGetImageWidth
+#define MagickGetNumberImages fn_MagickGetNumberImages
+#define MagickMergeImageLayers fn_MagickMergeImageLayers
+#define MagickFlattenImages fn_MagickFlattenImages
+#define MagickReadImage fn_MagickReadImage
+#define MagickReadImageBlob fn_MagickReadImageBlob
+#define MagickRelinquishMemory fn_MagickRelinquishMemory
+#define MagickRotateImage fn_MagickRotateImage
+#define MagickScaleImage fn_MagickScaleImage
+#define MagickSetFilename fn_MagickSetFilename
+#define MagickSetImageBackgroundColor fn_MagickSetImageBackgroundColor
+#define MagickSetIteratorIndex fn_MagickSetIteratorIndex
+#define MagickWandGenesis fn_MagickWandGenesis
+#define MagickWandTerminus fn_MagickWandTerminus
+#define NewMagickWand fn_NewMagickWand
+#define NewPixelIterator fn_NewPixelIterator
+#define NewPixelWand fn_NewPixelWand
+#define PixelGetAlpha fn_PixelGetAlpha
+#define PixelGetMagickColor fn_PixelGetMagickColor
+#define PixelGetNextIteratorRow fn_PixelGetNextIteratorRow
+#define PixelSetIteratorRow fn_PixelSetIteratorRow
+#define PixelSetPixelColor fn_PixelSetPixelColor
+#define PixelSetRed fn_PixelSetRed
+#define PixelSetGreen fn_PixelSetGreen
+#define PixelSetBlue fn_PixelSetBlue
+#define PixelSyncIterator fn_PixelSyncIterator
+#define DestroyExceptionInfo fn_DestroyExceptionInfo
+#define DestroyString fn_DestroyString
+#define AcquireExceptionInfo fn_AcquireExceptionInfo
+#define GetMagickList fn_GetMagickList
+
+#endif /* !WINDOWSNT */
+
 /* Log ImageMagick error message.
    Useful when a ImageMagick function returns the status `MagickFalse'.  */
 
@@ -8406,7 +8776,7 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
       PixelWand **source, **dest;
       size_t source_width, source_height;
       ssize_t source_left, source_top;
-      MagickPixelPacket pixel;
+      PixelInfo pixel;
       DisposeType dispose;
       ptrdiff_t lines = 0;
 
@@ -8471,7 +8841,7 @@ imagemagick_compute_animated_image (MagickWand *super_wand, int ino)
               if (dispose == BackgroundDispose || PixelGetAlpha (source[x]))
 		{
                   PixelGetMagickColor (source[x], &pixel);
-		  PixelSetMagickColor (dest[x + source_left], &pixel);
+                  PixelSetPixelColor (dest[x + source_left], &pixel);
 		}
             }
           PixelSyncIterator (dest_iterator);
@@ -8516,7 +8886,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
   MagickWand *image_wand;
   PixelIterator *iterator;
   PixelWand **pixels, *bg_wand = NULL;
-  MagickPixelPacket  pixel;
+  PixelInfo  pixel;
   Lisp_Object image;
   Lisp_Object value;
   Lisp_Object crop;
@@ -8912,6 +9282,11 @@ and `imagemagick-types-inhibit'.  */)
   char **imtypes;
   size_t i;
 
+#if WINDOWSNT
+          if (!init_imagemagick_functions ())
+            return Qnil;
+#endif
+
   ex = AcquireExceptionInfo();
   imtypes = GetMagickList ("*", &numf, ex);
   DestroyExceptionInfo(ex);
@@ -9926,12 +10368,16 @@ non-numeric, there is no explicit limit on the size of images.  */);
 #if defined (HAVE_IMAGEMAGICK)
   DEFSYM (Qimagemagick, "imagemagick");
   ADD_IMAGE_TYPE (Qimagemagick);
+#if defined HAVE_NTGUI && !defined CYGWIN
+  DEFSYM (Qmagickwand, "magickwand");
+  DEFSYM (Qmagickcore, "magickcore");
+#endif /* HAVE_NTGUI */
 #endif
 
 #if defined (HAVE_RSVG)
   DEFSYM (Qsvg, "svg");
   ADD_IMAGE_TYPE (Qsvg);
-#ifdef HAVE_NTGUI
+#if defined (HAVE_NTGUI) && !defined (CYGWIN)
   /* Other libraries used directly by svg code.  */
   DEFSYM (Qgdk_pixbuf, "gdk-pixbuf");
   DEFSYM (Qglib, "glib");

  reply	other threads:[~2017-01-21 20:40 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-20  1:40 64-bit build on Windows Juanma Barranquero
2017-01-20  8:06 ` Eli Zaretskii
2017-01-21 18:29   ` Juanma Barranquero
2017-01-21 18:38     ` Eli Zaretskii
2017-01-20 13:42 ` Phillip Lord
2017-01-20 14:32   ` Óscar Fuentes
2017-01-20 15:54     ` Eli Zaretskii
2017-01-20 19:51       ` Fabrice Popineau
2017-01-21 18:25         ` Eli Zaretskii
2017-01-21 19:04           ` Fabrice Popineau
2017-01-21 19:15             ` Juanma Barranquero
2017-01-21 19:23               ` Fabrice Popineau
2017-01-21 19:30                 ` Juanma Barranquero
2017-01-21 19:55                 ` Eli Zaretskii
2017-01-21 20:40                   ` Fabrice Popineau [this message]
2017-01-22 16:50                     ` Eli Zaretskii
2017-01-22 20:38                       ` Fabrice Popineau
2017-01-22 21:22                         ` Paul Eggert
2017-01-22 21:39                           ` Fabrice Popineau
2017-01-23  3:37                           ` Eli Zaretskii
2017-01-23  3:30                         ` Eli Zaretskii
2017-01-21 18:57       ` Juanma Barranquero
2017-01-21 19:52         ` Eli Zaretskii
2017-01-21 21:15           ` Juanma Barranquero
2017-01-21 21:42           ` Juanma Barranquero
2017-01-21 22:30             ` Nikolay Kudryavtsev
2017-01-21 22:43             ` Óscar Fuentes
2017-01-22  3:38               ` Eli Zaretskii
2017-01-21 21:18         ` Juanma Barranquero
2017-01-22 17:50           ` Stephen Leake
2017-01-22 18:07             ` Eli Zaretskii
2017-01-22 20:30               ` Fabrice Popineau
2017-01-21 18:37     ` Juanma Barranquero
2017-01-26 19:05       ` Arash Esbati
2017-01-27  6:07         ` Fabrice Popineau
  -- strict thread matches above, loose matches on Subject: below --
2017-01-21 23:12 Angelo Graziosi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAFgFV9PbyVqoi1O1EGByAo-BQt_Jd-cK_exn-BqUTVd1WYh73w@mail.gmail.com \
    --to=fabrice.popineau@gmail.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=lekktu@gmail.com \
    --cc=ofv@wanadoo.es \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.