summary refs log tree commit diff
path: root/gnu/packages
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages')
-rw-r--r--gnu/packages/abduco.scm4
-rw-r--r--gnu/packages/abiword.scm39
-rw-r--r--gnu/packages/acl.scm2
-rw-r--r--gnu/packages/admin.scm39
-rw-r--r--gnu/packages/algebra.scm151
-rw-r--r--gnu/packages/animation.scm2
-rw-r--r--gnu/packages/anthy.scm64
-rw-r--r--gnu/packages/apr.scm2
-rw-r--r--gnu/packages/audacity.scm2
-rw-r--r--gnu/packages/audio.scm14
-rw-r--r--gnu/packages/autotools.scm8
-rw-r--r--gnu/packages/avahi.scm2
-rw-r--r--gnu/packages/backup.scm19
-rw-r--r--gnu/packages/base.scm35
-rw-r--r--gnu/packages/bash.scm2
-rw-r--r--gnu/packages/bioinformatics.scm390
-rw-r--r--gnu/packages/bittorrent.scm4
-rw-r--r--gnu/packages/bootstrap.scm8
-rw-r--r--gnu/packages/c.scm127
-rw-r--r--gnu/packages/cdrom.scm2
-rw-r--r--gnu/packages/ci.scm8
-rw-r--r--gnu/packages/cmake.scm2
-rw-r--r--gnu/packages/compression.scm69
-rw-r--r--gnu/packages/cpio.scm2
-rw-r--r--gnu/packages/cross-base.scm2
-rw-r--r--gnu/packages/cups.scm117
-rw-r--r--gnu/packages/databases.scm8
-rw-r--r--gnu/packages/dav.scm10
-rw-r--r--gnu/packages/dico.scm5
-rw-r--r--gnu/packages/dillo.scm63
-rw-r--r--gnu/packages/docbook.scm30
-rw-r--r--gnu/packages/doxygen.scm2
-rw-r--r--gnu/packages/ebook.scm6
-rw-r--r--gnu/packages/elf.scm5
-rw-r--r--gnu/packages/emacs.scm74
-rw-r--r--gnu/packages/engineering.scm29
-rw-r--r--gnu/packages/firmware.scm2
-rw-r--r--gnu/packages/flashing-tools.scm6
-rw-r--r--gnu/packages/fltk.scm5
-rw-r--r--gnu/packages/fonts.scm51
-rw-r--r--gnu/packages/fontutils.scm231
-rw-r--r--gnu/packages/ftp.scm7
-rw-r--r--gnu/packages/game-development.scm33
-rw-r--r--gnu/packages/games.scm243
-rw-r--r--gnu/packages/gawk.scm2
-rw-r--r--gnu/packages/gcc.scm10
-rw-r--r--gnu/packages/gd.scm5
-rw-r--r--gnu/packages/ghostscript.scm4
-rw-r--r--gnu/packages/gimp.scm53
-rw-r--r--gnu/packages/glib.scm28
-rw-r--r--gnu/packages/gnome.scm50
-rw-r--r--gnu/packages/gnucash.scm2
-rw-r--r--gnu/packages/gnunet.scm2
-rw-r--r--gnu/packages/gnupg.scm35
-rw-r--r--gnu/packages/gnustep.scm89
-rw-r--r--gnu/packages/gnuzilla.scm65
-rw-r--r--gnu/packages/graphics.scm75
-rw-r--r--gnu/packages/grub.scm6
-rw-r--r--gnu/packages/gtk.scm10
-rw-r--r--gnu/packages/guile.scm20
-rw-r--r--gnu/packages/ibus.scm54
-rw-r--r--gnu/packages/icu4c.scm6
-rw-r--r--gnu/packages/idutils.scm3
-rw-r--r--gnu/packages/image.scm98
-rw-r--r--gnu/packages/imagemagick.scm2
-rw-r--r--gnu/packages/irc.scm6
-rw-r--r--gnu/packages/java.scm149
-rw-r--r--gnu/packages/kde-frameworks.scm8
-rw-r--r--gnu/packages/ldc.scm2
-rw-r--r--gnu/packages/libcanberra.scm2
-rw-r--r--gnu/packages/libevent.scm7
-rw-r--r--gnu/packages/libreoffice.scm2
-rw-r--r--gnu/packages/libunwind.scm2
-rw-r--r--gnu/packages/libusb.scm49
-rw-r--r--gnu/packages/linux.scm107
-rw-r--r--gnu/packages/lirc.scm2
-rw-r--r--gnu/packages/llvm.scm2
-rw-r--r--gnu/packages/lsh.scm2
-rw-r--r--gnu/packages/lua.scm10
-rw-r--r--gnu/packages/lxde.scm8
-rw-r--r--gnu/packages/lxqt.scm2
-rw-r--r--gnu/packages/machine-learning.scm19
-rw-r--r--gnu/packages/mail.scm24
-rw-r--r--gnu/packages/make-bootstrap.scm6
-rw-r--r--gnu/packages/marst.scm43
-rw-r--r--gnu/packages/maths.scm64
-rw-r--r--gnu/packages/mcrypt.scm2
-rw-r--r--gnu/packages/messaging.scm13
-rw-r--r--gnu/packages/mit-krb5.scm8
-rw-r--r--gnu/packages/mp3.scm13
-rw-r--r--gnu/packages/mpd.scm18
-rw-r--r--gnu/packages/mpi.scm10
-rw-r--r--gnu/packages/multiprecision.scm34
-rw-r--r--gnu/packages/music.scm166
-rw-r--r--gnu/packages/networking.scm21
-rw-r--r--gnu/packages/ninja.scm4
-rw-r--r--gnu/packages/node.scm77
-rw-r--r--gnu/packages/nvi.scm6
-rw-r--r--gnu/packages/ocaml.scm3
-rw-r--r--gnu/packages/openldap.scm23
-rw-r--r--gnu/packages/openstack.scm29
-rw-r--r--gnu/packages/orpheus.scm2
-rw-r--r--gnu/packages/ots.scm3
-rw-r--r--gnu/packages/package-management.scm7
-rw-r--r--gnu/packages/parallel.scm4
-rw-r--r--gnu/packages/patches/abiword-link-plugins-against-backend.patch639
-rw-r--r--gnu/packages/patches/abiword-no-include-glib-internal-headers.patch13
-rw-r--r--gnu/packages/patches/abiword-pass-no-undefined-to-linker.patch608
-rw-r--r--gnu/packages/patches/abiword-use-proper-png-api.patch175
-rw-r--r--gnu/packages/patches/asymptote-gsl2.patch33
-rw-r--r--gnu/packages/patches/fltk-xfont-on-demand.patch45
-rw-r--r--gnu/packages/patches/fontforge-svg-modtime.patch35
-rw-r--r--gnu/packages/patches/fossil-test-fixes.patch189
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-4477.patch37
-rw-r--r--gnu/packages/patches/icecat-CVE-2015-7207.patch1140
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch356
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch58
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch60
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch53
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch32
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch103
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1954.patch32
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1960.patch55
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1961.patch33
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1962.patch107
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1964.patch54
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1965.patch44
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1966.patch36
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-1974.patch530
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2805.patch75
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2807-pt1.patch35
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2807-pt2.patch69
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2807-pt3.patch33
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2807-pt4.patch37
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2807-pt5.patch35
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2808.patch389
-rw-r--r--gnu/packages/patches/icecat-CVE-2016-2814.patch35
-rw-r--r--gnu/packages/patches/icecat-bug-1248851.patch37
-rw-r--r--gnu/packages/patches/icecat-update-bundled-graphite2.patch2488
-rw-r--r--gnu/packages/patches/icecat-update-graphite2-pt2.patch861
-rw-r--r--gnu/packages/patches/icecat-update-graphite2.patch9988
-rw-r--r--gnu/packages/patches/imlib2-CVE-2016-4024.patch52
-rw-r--r--gnu/packages/patches/openssh-CVE-2015-8325.patch31
-rw-r--r--gnu/packages/patches/poppler-CVE-2015-8868.patch30
-rw-r--r--gnu/packages/patches/python-pandas-fix-tslib-test-failure.patch141
-rw-r--r--gnu/packages/patches/ruby-symlinkfix.patch53
-rw-r--r--gnu/packages/patches/ttf2eot-cstddef.patch12
-rw-r--r--gnu/packages/patches/ttfautohint-source-date-epoch.patch70
-rw-r--r--gnu/packages/patches/woff2-libbrotli.patch84
-rw-r--r--gnu/packages/patchutils.scm16
-rw-r--r--gnu/packages/pcre.scm12
-rw-r--r--gnu/packages/pdf.scm13
-rw-r--r--gnu/packages/perl.scm18
-rw-r--r--gnu/packages/plotutils.scm28
-rw-r--r--gnu/packages/polkit.scm2
-rw-r--r--gnu/packages/pretty-print.scm3
-rw-r--r--gnu/packages/pulseaudio.scm6
-rw-r--r--gnu/packages/python.scm594
-rw-r--r--gnu/packages/qemu.scm27
-rw-r--r--gnu/packages/qt.scm5
-rw-r--r--gnu/packages/ratpoison.scm2
-rw-r--r--gnu/packages/rdf.scm7
-rw-r--r--gnu/packages/readline.scm2
-rw-r--r--gnu/packages/ruby.scm23
-rw-r--r--gnu/packages/rush.scm2
-rw-r--r--gnu/packages/samba.scm4
-rw-r--r--gnu/packages/scheme.scm13
-rw-r--r--gnu/packages/screen.scm2
-rw-r--r--gnu/packages/sdl.scm2
-rw-r--r--gnu/packages/slim.scm6
-rw-r--r--gnu/packages/ssh.scm7
-rw-r--r--gnu/packages/statistics.scm589
-rw-r--r--gnu/packages/tcl.scm6
-rw-r--r--gnu/packages/tcsh.scm2
-rw-r--r--gnu/packages/telephony.scm3
-rw-r--r--gnu/packages/texinfo.scm4
-rw-r--r--gnu/packages/textutils.scm36
-rw-r--r--gnu/packages/tls.scm31
-rw-r--r--gnu/packages/tor.scm2
-rw-r--r--gnu/packages/tv.scm8
-rw-r--r--gnu/packages/valgrind.scm2
-rw-r--r--gnu/packages/version-control.scm106
-rw-r--r--gnu/packages/video.scm111
-rw-r--r--gnu/packages/vpn.scm2
-rw-r--r--gnu/packages/vtk.scm2
-rw-r--r--gnu/packages/w3m.scm8
-rw-r--r--gnu/packages/web.scm86
-rw-r--r--gnu/packages/webkit.scm8
-rw-r--r--gnu/packages/wicd.scm10
-rw-r--r--gnu/packages/wm.scm2
-rw-r--r--gnu/packages/wxwidgets.scm10
-rw-r--r--gnu/packages/xdisorg.scm153
-rw-r--r--gnu/packages/xfce.scm66
-rw-r--r--gnu/packages/xiph.scm41
-rw-r--r--gnu/packages/xml.scm4
-rw-r--r--gnu/packages/xorg.scm25
-rw-r--r--gnu/packages/zip.scm26
197 files changed, 8444 insertions, 16219 deletions
diff --git a/gnu/packages/abduco.scm b/gnu/packages/abduco.scm
index ae67f81849..3cb84f5fc8 100644
--- a/gnu/packages/abduco.scm
+++ b/gnu/packages/abduco.scm
@@ -25,7 +25,7 @@
 (define-public abduco
   (package
    (name "abduco")
-   (version "0.5")
+   (version "0.6")
    (source (origin
             (method url-fetch)
             (uri (string-append
@@ -33,7 +33,7 @@
                   version ".tar.gz"))
             (sha256
              (base32
-              "11phry5wnvwm9ckij5gxbrjfgdz3x38vpnm505q5ldc88im248mz"))))
+              "1x1m58ckwsprljgmdy93mvgjyg9x3cqrzdf3mysp0mx97zhhj2f9"))))
    (build-system gnu-build-system)
    (arguments
     `(#:make-flags (list "CC=gcc"
diff --git a/gnu/packages/abiword.scm b/gnu/packages/abiword.scm
index c6f259a2dd..8e89bb2f52 100644
--- a/gnu/packages/abiword.scm
+++ b/gnu/packages/abiword.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 Marek Benc <merkur32@gmail.com>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,6 +23,7 @@
   #:use-module (guix download)
   #:use-module (guix build-system gnu)
   #:use-module (gnu packages)
+  #:use-module (gnu packages autotools)
   #:use-module (gnu packages boost)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages enchant)
@@ -41,7 +43,7 @@
 (define-public abiword
   (package
     (name "abiword")
-    (version "2.8.6")
+    (version "3.0.1")
     (source
       (origin
         (method url-fetch)
@@ -49,15 +51,10 @@
           (string-append "http://abisource.org/downloads/" name "/" version
                          "/source/" name "-" version ".tar.gz"))
         (sha256
-          (base32 "059sd2apxdmcacc4pll880i7vm18h0kyjsq299m1mz3c7ak8k46r"))
+          (base32 "1ik591rx15nn3n1297cwykl8wvrlgj78i528id9wbidgy3xzd570"))
         (patches
-          (list
-            (search-patch "abiword-wmf-version-lookup-fix.patch")
-            (search-patch "abiword-no-include-glib-internal-headers.patch")
-            (search-patch "abiword-explictly-cast-bools.patch")
-            (search-patch "abiword-use-proper-png-api.patch")
-            (search-patch "abiword-pass-no-undefined-to-linker.patch")
-            (search-patch "abiword-link-plugins-against-backend.patch")))))
+         (search-patches "abiword-wmf-version-lookup-fix.patch"
+                         "abiword-explictly-cast-bools.patch"))))
 
     (build-system gnu-build-system)
     (arguments                   ;; NOTE: rsvg is disabled, since Abiword
@@ -65,22 +62,31 @@
         (list
           "--enable-clipart"     ;; TODO: The following plugins have unresolved
           "--enable-templates"   ;; dependencies: aiksaurus, grammar, wpg, gda,
-          (string-append         ;; wordperfect, psion, mathview, goffice.
+          (string-append         ;; wordperfect, psion, mathview.
             "--enable-plugins="
               "applix " "babelfish " "bmp " "clarisworks " "collab " "command "
-              "docbook " "eml " "freetranslation " "garble " "gdict " "gimp "
-              "google " "hancom " "hrtext " "iscii " "kword " "latex "
-              "loadbindings " "mht " "mif " "mswrite " "opendocument "
+              "docbook " "eml " "epub " "freetranslation " "garble " "gdict "
+              "gimp " "goffice " "google " "hancom " "hrtext " "iscii " "kword "
+              "latex " "loadbindings " "mht " "mif " "mswrite " "opendocument "
               "openwriter " "openxml " "opml " "ots " "paint " "passepartout "
               "pdb " "pdf " "presentation " "s5 " "sdw " "t602 " "urldict "
-              "wikipedia " "wmf " "wml " "xslfo"))))
+              "wikipedia " "wmf " "wml " "xslfo"))
+        ;; tests fail with: Gtk-CRITICAL **: gtk_settings_get_for_screen:
+        ;;                  assertion 'GDK_IS_SCREEN (screen)' failed
+        ;;                  GLib-GObject-CRITICAL **: g_object_get_qdata:
+        ;;                  assertion 'G_IS_OBJECT (object)' failed
+        ;; Manually starting the X server before the test phase did not help
+        ;; the tests to pass.
+        #:tests? #f))
     (inputs
       `(("boost" ,boost)
         ("enchant" ,enchant)
         ("fontconfig" ,fontconfig)
         ("fribidi" ,fribidi)
         ("glib" ,glib)
-        ("gtk+" ,gtk+-2)
+        ("goffice" ,goffice)
+        ("gtk+" ,gtk+)
+        ("libchamplain" ,libchamplain)
         ("libglade" ,libglade)
         ("libgsf" ,libgsf)
         ("libjpeg" ,libjpeg)
@@ -88,14 +94,17 @@
         ("librsvg" ,librsvg)
         ("libwmf" ,libwmf)
         ("libxml2" ,libxml2)
+        ("libxslt" ,libxslt)
         ("ots" ,ots)
         ("popt" ,popt)
         ("readline" ,readline)
+        ("telepathy" ,telepathy-glib)
         ("wv" ,wv)
         ("zlib" ,zlib)))
     (native-inputs
       `(("intltool" ,intltool)
         ("glib:bin" ,glib "bin")
+        ("libtool" ,libtool)
         ("pkg-config" ,pkg-config)))
     (home-page "http://abisource.org/")
     (synopsis "Word processing program")
diff --git a/gnu/packages/acl.scm b/gnu/packages/acl.scm
index 784186b670..415fae496b 100644
--- a/gnu/packages/acl.scm
+++ b/gnu/packages/acl.scm
@@ -41,7 +41,7 @@
       (sha256
        (base32
         "08qd9s3wfhv0ajswsylnfwr5h0d7j9d4rgip855nrh400nxp940p"))
-      (patches (list (search-patch "acl-hurd-path-max.patch")))))
+      (patches (search-patches "acl-hurd-path-max.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f   ; FIXME: Investigate test suite failures
diff --git a/gnu/packages/admin.scm b/gnu/packages/admin.scm
index 9636ee939f..11a2d1622b 100644
--- a/gnu/packages/admin.scm
+++ b/gnu/packages/admin.scm
@@ -100,6 +100,35 @@ usual file attributes can be checked for inconsistencies.")
     (home-page "http://aide.sourceforge.net/")
     (license license:gpl2+)))
 
+(define-public progress
+  (package
+    (name "progress")
+    (version "0.13")
+    (source (origin
+      (method url-fetch)
+      (uri (string-append "https://github.com/Xfennec/"
+                          name "/archive/v" version ".tar.gz"))
+      (sha256
+       (base32 "133iar4vq5vlklydb4cyazjy6slmpbndrws474mg738bd8avc30n"))
+      (file-name (string-append name "-" version ".tar.gz"))))
+    (build-system gnu-build-system)
+    (inputs
+     `(("ncurses" ,ncurses)))
+    (arguments
+     `(#:tests? #f ; There is no test suite.
+       #:make-flags (list "CC=gcc" "LDFLAGS+=-lncurses"
+                          (string-append "PREFIX=" (assoc-ref %outputs "out")))
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)))) ; There's no configure phase.
+    (home-page "https://github.com/Xfennec/progress")
+    (synopsis "Program to view the progress of the coreutils commands")
+    (description "A program that looks for coreutils basic commands (cp, mv,
+dd, tar, gzip/gunzip, cat, etc.) currently running on your system and displays
+the percentage of copied data.  It can also show estimated time and throughput,
+and provides a \"top-like\" mode (monitoring).")
+    (license license:gpl3+)))
+
 (define-public dmd
   ;; Deprecated.  Kept around "just in case."
   (let ((base-version "0.2")
@@ -768,7 +797,7 @@ system administrator.")
               (sha256
                (base32
                 "0263gi6i19fyzzc488n0qw3m518i39f6a7qmrfvahk9j10bkh5j3"))
-              (patches (list (search-patch "sudo-CVE-2015-5602.patch")))))
+              (patches (search-patches "sudo-CVE-2015-5602.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags
@@ -842,10 +871,10 @@ commands and their arguments.")
                (base32
                 "05mkp5bx1c3z7h5biddsv0p49gkrq9ksany3anp4wdiv92p5prfc"))
               (patches
-               (map search-patch '("wpa-supplicant-CVE-2015-5310.patch"
-                                   "wpa-supplicant-CVE-2015-5314.patch"
-                                   "wpa-supplicant-CVE-2015-5315.patch"
-                                   "wpa-supplicant-CVE-2015-5316.patch")))))
+               (search-patches "wpa-supplicant-CVE-2015-5310.patch"
+                               "wpa-supplicant-CVE-2015-5314.patch"
+                               "wpa-supplicant-CVE-2015-5315.patch"
+                               "wpa-supplicant-CVE-2015-5316.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-replace
diff --git a/gnu/packages/algebra.scm b/gnu/packages/algebra.scm
index a7455feb88..f03c3c104e 100644
--- a/gnu/packages/algebra.scm
+++ b/gnu/packages/algebra.scm
@@ -1,7 +1,9 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2012, 2013, 2014, 2015, 2016 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2013, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;;; Copyright © 2014 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,12 +24,21 @@
   #:use-module (gnu packages)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages compression)
+  #:use-module (gnu packages doxygen)
+  #:use-module (gnu packages fltk)
+  #:use-module (gnu packages gl)
+  #:use-module (gnu packages graphviz)
+  #:use-module (gnu packages image)
   #:use-module (gnu packages multiprecision)
+  #:use-module (gnu packages maths)
   #:use-module (gnu packages mpi)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages readline)
   #:use-module (gnu packages flex)
+  #:use-module (gnu packages python)
+  #:use-module (gnu packages tcsh)
   #:use-module (gnu packages texlive)
+  #:use-module (gnu packages xiph)
   #:use-module (gnu packages xorg)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix packages)
@@ -188,6 +199,68 @@ GP2C, the GP to C compiler, translates GP scripts to PARI programs.")
    (license license:gpl2)
    (home-page "http://pari.math.u-bordeaux.fr/")))
 
+(define-public giac-xcas
+  (package
+    (name "giac-xcas")
+    (version "1.2.2-41")
+    (source (origin
+              (method url-fetch)
+              ;; "~parisse/giac" is not used because the maintainer regularly
+              ;; overwrites the release tarball there, introducing a checksum
+              ;; mismatch every time.  See
+              ;; <https://www-fourier.ujf-grenoble.fr/~parisse/debian/dists/stable/main/source/README>
+              (uri (string-append "https://www-fourier.ujf-grenoble.fr/"
+                                  "~parisse/debian/dists/stable/main/"
+                                  "source/giac_" version ".tar.gz"))
+              (sha256
+               (base32
+                "061a0p5l1qlb9iqk7n7yznhv2f3hvll1hrzjbhn81bf31f2wj6sq"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'patch-bin-cp
+           (lambda _
+             ;; Some Makefiles contain hard-coded "/bin/cp".
+             (substitute* (find-files "doc" "^Makefile")
+               (("/bin/cp") (which "cp")))
+             #t))
+         (add-after 'unpack 'disable-broken-test
+           (lambda _
+             ;; Disable failing test.  Actually, the results are correct but
+             ;; a sorting discrepancy prevents the test from being validated.
+             (substitute* "check/Makefile.in"
+               (("chk_fhan16") ""))
+             #t)))))
+    (inputs
+     `(("fltk" ,fltk)
+       ("gmp" ,gmp)
+       ("gsl" ,gsl)
+       ("lapack" ,lapack)
+       ("libao" ,ao)
+       ("libjpeg" ,libjpeg)
+       ("libpng" ,libpng)
+       ("libx11" ,libx11)
+       ("libxinerama" ,libxinerama)
+       ("libxft" ,libxft)
+       ("libxt" ,libxt)
+       ("mesa" ,mesa)
+       ("mpfi" ,mpfi)
+       ("mpfr" ,mpfr)
+       ("ntl" ,ntl)
+       ("perl" ,perl)
+       ("pari-gp" ,pari-gp)
+       ("tcsh" ,tcsh)
+       ("texlive" ,texlive-minimal)))
+    (native-inputs `(("readline" ,readline)))
+    (home-page "https://www-fourier.ujf-grenoble.fr/~parisse/giac.html")
+    (synopsis "Computer algebra system")
+    (description
+     "Giac/Xcas is a computer algebra system.  It has a compatibility mode for
+maple, mupad and the TI89.  It is available as a standalone program (graphic
+or text interfaces) or as a C++ library.")
+    (license license:gpl3+)))
+
 (define-public flint
   (package
    (name "flint")
@@ -199,7 +272,7 @@ GP2C, the GP to C compiler, translates GP scripts to PARI programs.")
                   version ".tar.gz"))
             (sha256 (base32
                      "11syazv1a8rrnac3wj3hnyhhflpqcmq02q8pqk2m6g2k6h0gxwfb"))
-            (patches (map search-patch '("flint-ldconfig.patch")))))
+            (patches (search-patches "flint-ldconfig.patch"))))
    (build-system gnu-build-system)
    (propagated-inputs
     `(("gmp" ,gmp)
@@ -248,7 +321,7 @@ fast arithmetic.")
             (sha256
               (base32
                 "04hhcpshfkcq9fr4hixbhpps50yf9drk62xgkvlcaj5kb4nyrx7l"))
-            (patches (map search-patch '("arb-ldconfig.patch")))))
+            (patches (search-patches "arb-ldconfig.patch"))))
    (build-system gnu-build-system)
    (propagated-inputs
     `(("flint" ,flint))) ; flint.h is included by arf.h
@@ -322,6 +395,76 @@ matrices, and polynomials over the integers and over finite fields.")
    (license license:gpl2+)
    (home-page "http://shoup.net/ntl/")))
 
+(define-public singular
+  (package
+   (name "singular")
+   (version "4.0.3")
+   (source (origin
+            (method url-fetch)
+            (uri (string-append "http://www.mathematik.uni-kl.de/ftp/pub/"
+                                "Math/Singular/SOURCES/"
+                                (string-join (string-split version #\.) "-")
+                                "/singular-" version ".tar.gz"))
+            (sha256 (base32
+                     "0viidy2fz62rln9p0s9qfs7fnm55c6fw1agydd1py26gxylp1ksc"))))
+   (build-system gnu-build-system)
+   (native-inputs
+    `(("doxygen" ,doxygen)
+      ("graphviz" ,graphviz)
+      ("perl" ,perl)))
+   (inputs
+    `(("cddlib" ,cddlib)
+      ("gmp" ,gmp)
+      ("flint" ,flint)
+      ("mpfr" ,mpfr)
+      ("ntl" ,ntl)
+      ("python" ,python-2)
+      ("readline" ,readline)))
+   (arguments
+    `(#:configure-flags
+      (list (string-append "--with-ntl="
+                           (assoc-ref %build-inputs "ntl")))))
+   (synopsis "Computer algebra system for polynomial computations")
+   (description
+    "Singular is a computer algebra system for polynomial computations,
+with special emphasis on commutative and non-commutative algebra, algebraic
+geometry and singularity theory.")
+   ;; Singular itself is dual licensed gpl2 or gpl3, but some of the
+   ;; libraries with which it links are licensed under lgpl3+, so the
+   ;; combined work becomes gpl3. See COPYING in the source code.
+   (license license:gpl3)
+   (home-page "http://www.singular.uni-kl.de/index.php")))
+
+(define-public gmp-ecm
+  (package
+   (name "gmp-ecm")
+   (version "7.0")
+   (source (origin
+            (method url-fetch)
+            (uri (string-append "https://gforge.inria.fr/frs/download.php/"
+                                "file/35642/ecm-"
+                                version ".tar.gz"))
+            (sha256 (base32
+                     "00jzzwqp49m01vwsr9z1w7bvm8lb69l3f62x7qr8sfz0xiczxnpm"))))
+   (build-system gnu-build-system)
+   (inputs
+    `(("gmp" ,gmp)))
+   (arguments
+    `(#:configure-flags '("--enable-shared"
+                          ;; Disable specific assembly routines, which depend
+                          ;; on the subarchitecture of the build machine,
+                          ;; and use gmp instead.
+                          "--disable-asm-redc")))
+   (synopsis "Integer factorization library using the elliptic curve method")
+   (description
+    "GMP-ECM factors integers using the elliptic curve method (ECM) as well
+as the P-1 and P+1 algorithms.  It provides a library and a stand-alone
+binary.")
+   ;; Most files are under lgpl3+, but some are under gpl3+ or gpl2+,
+   ;; so the combined work is under gpl3+.
+   (license license:gpl3+)
+   (home-page "http://ecm.gforge.inria.fr/")))
+
 (define-public bc
   (package
     (name "bc")
@@ -424,14 +567,14 @@ cosine/ sine transforms or DCT/DST).")
 (define-public eigen
   (package
     (name "eigen")
-    (version "3.2.7")
+    (version "3.2.8")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://bitbucket.org/eigen/eigen/get/"
                                   version ".tar.bz2"))
               (sha256
                (base32
-                "0gigbjjdlw2q0gvcnyiwc6in314a647rkidk6977bwiwn88im3p5"))
+                "0mby6my1djsg8681fcvlaq0i4kd17fja9qn5f713j3xpfbb66akj"))
               (file-name (string-append name "-" version ".tar.bz2"))
               (modules '((guix build utils)))
               (snippet
diff --git a/gnu/packages/animation.scm b/gnu/packages/animation.scm
index 789bb6e6f2..077657937d 100644
--- a/gnu/packages/animation.scm
+++ b/gnu/packages/animation.scm
@@ -68,7 +68,7 @@ C++ @dfn{Standard Template Library} (STL).")
               (sha256
                (base32
                 "1d3z2r78j3rkff47q3wl0ami69y3l4nyi5r9zclymb8ar7mgkk9l"))
-              (patches (list (search-patch "synfig-build-fix.patch")))))
+              (patches (search-patches "synfig-build-fix.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags
diff --git a/gnu/packages/anthy.scm b/gnu/packages/anthy.scm
new file mode 100644
index 0000000000..7cd35b622d
--- /dev/null
+++ b/gnu/packages/anthy.scm
@@ -0,0 +1,64 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 Guix 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages anthy)
+  #:use-module (guix licenses)
+  #:use-module (guix packages)
+  #:use-module (guix download)
+  #:use-module (guix build-system gnu))
+
+(define-public anthy
+  (package
+    (name "anthy")
+    (version "9100h")
+    (source (origin
+              (method url-fetch)
+              ;; The URI does not appear to be easily guessable.  For
+              ;; example, you cannot download version "9100g" simply
+              ;; by replacing "9100h" in the URI.
+              (uri "http://tcpdiag.dl.osdn.jp/anthy/37536/anthy-9100h.tar.gz")
+              (sha256
+               (base32
+                "0ism4zibcsa5nl77wwi12vdsfjys3waxcphn1p5s7d0qy1sz0mnj"))))
+    (build-system gnu-build-system)
+    ;; Anthy also contains elisp modules for using anthy within Emacs.
+    ;; However, these modules are incompatible with the latest version
+    ;; of Emacs.  This is because they rely on the presence of
+    ;; last-command-char, which was removed in Emacs 24.3.  So, we
+    ;; don't try to install them here at this time.
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (replace 'check
+           (lambda _
+             (with-directory-excursion "test"
+               (zero? (system* "./anthy" "--all"))))))))
+    (home-page "http://anthy.osdn.jp/")
+    (synopsis "Japanese input method")
+    (description "Anthy is a Japanese input method for converting
+hiragana text to mixed kana and kanji.  It is written in the C
+programming language.  Anthy stores personal customizations (words it
+has learned from the user's input, words the user has explicitly
+added, etc.) in the ~/.anthy/ directory.  This package contains the
+anthy C libraries, the cannadic and alt-cannadic kana dictionaries, as
+well as command-line tools for using anthy and managing
+dictionaries.")
+    ;; Most of anthy is lgpl2.1+.  However, some files (e.g., from
+    ;; alt-cannadic) use gpl2.  See the file "COPYING" in the anthy
+    ;; source for details.
+    (license (list lgpl2.1+ gpl2))))
diff --git a/gnu/packages/apr.scm b/gnu/packages/apr.scm
index 8c57ee3ab2..17945c0390 100644
--- a/gnu/packages/apr.scm
+++ b/gnu/packages/apr.scm
@@ -39,7 +39,7 @@
               (base32
                "0ypn51xblix5ys9xy7da3ngdydip0qqh9rdq8nz54w9aq8lys0vx"))
              (patches
-              (list (search-patch "apr-skip-getservbyname-test.patch")))
+              (search-patches "apr-skip-getservbyname-test.patch"))
              (patch-flags '("-p0"))))
     (build-system gnu-build-system)
     (arguments
diff --git a/gnu/packages/audacity.scm b/gnu/packages/audacity.scm
index 53cc2a497e..9eae6aa1aa 100644
--- a/gnu/packages/audacity.scm
+++ b/gnu/packages/audacity.scm
@@ -47,7 +47,7 @@
          "mirror://sourceforge/audacity/audacity-minsrc-" version ".tar.xz"))
        (sha256
         (base32 "1cs2w3fwqylpqmfwkvlgdx5lhclpckfil7pqibl37qlbnf4qvndh"))
-       (patches (list (search-patch "audacity-fix-ffmpeg-binding.patch")))))
+       (patches (search-patches "audacity-fix-ffmpeg-binding.patch"))))
     (build-system gnu-build-system)
     (inputs
      ;; TODO: Add portSMF and libwidgetextra once they're packaged.  In-tree
diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm
index ca438f8077..bcb3b77b88 100644
--- a/gnu/packages/audio.scm
+++ b/gnu/packages/audio.scm
@@ -333,7 +333,7 @@ tools (analyzer, mono/stereo tools, crossovers).")
               (sha256
                (base32
                 "0a1sni6lr7qpwywpggbkp0ia3h9bwwgf9i87gsag8ra2h30v82hd"))
-              (patches (list (search-patch "csound-header-ordering.patch")))))
+              (patches (search-patches "csound-header-ordering.patch"))))
     (build-system cmake-build-system)
     (arguments
      ;; Work around this error on x86_64 with libc 2.22+:
@@ -862,15 +862,15 @@ patches that can be used with softsynths such as Timidity and WildMidi.")
 (define-public guitarix
   (package
     (name "guitarix")
-    (version "0.34.0")
+    (version "0.35.0")
     (source (origin
              (method url-fetch)
              (uri (string-append
                    "mirror://sourceforge/guitarix/guitarix2-"
-                   version ".tar.bz2"))
+                   version ".tar.xz"))
              (sha256
               (base32
-               "0pamaq8iybsaglq6y1m1rlmz4wgbs2r6m24bj7x4fwg4grjvzjl8"))))
+               "10hijqrrl8xil46kgsac10ysfxysisxlibm2rz133zyig5n63jdw"))))
     (build-system waf-build-system)
     (arguments
      `(#:tests? #f ; no "check" target
@@ -2064,7 +2064,7 @@ portions of LAME.")
              ".tgz"))
        (sha256
         (base32 "0mwddk4qzybaf85wqfhxqlf0c5im9il8z03rd4n127k8y2jj9q4g"))
-       (patches (list (search-patch "portaudio-audacity-compat.patch")))))
+       (patches (search-patches "portaudio-audacity-compat.patch"))))
     (build-system gnu-build-system)
     (inputs
      ;; TODO: Add ASIHPI.
@@ -2096,14 +2096,14 @@ interface.")
 (define-public qsynth
   (package
     (name "qsynth")
-    (version "0.4.0")
+    (version "0.4.1")
     (source
      (origin
        (method url-fetch)
        (uri (string-append
              "mirror://sourceforge/qsynth/qsynth-" version ".tar.gz"))
        (sha256
-        (base32 "1chc89v9hcjw3k4rvzakl8g56wv24kh48fzv1gfs4iv8vhyl3j4x"))))
+        (base32 "034p6mbwrjnxd9b6h20cidxi4ilkk3cgpjp154j0jzjs1ipf7x2h"))))
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f)) ; no "check" phase
diff --git a/gnu/packages/autotools.scm b/gnu/packages/autotools.scm
index 598624ccdc..ddc628d005 100644
--- a/gnu/packages/autotools.scm
+++ b/gnu/packages/autotools.scm
@@ -195,9 +195,8 @@ output is indexed in many ways to simplify browsing.")
               (base32
                "0dl6vfi2lzz8alnklwxzfz624b95hb1ipjvd3mk177flmddcf24r"))
              (patches
-              (map search-patch
-                   '("automake-regexp-syntax.patch"
-                     "automake-skip-amhello-tests.patch")))))
+              (search-patches "automake-regexp-syntax.patch"
+                              "automake-skip-amhello-tests.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("autoconf" ,(autoconf-wrapper))
@@ -273,8 +272,7 @@ Makefile, simplifying the entire process for the developer.")
               (sha256
                (base32
                 "0vxj52zm709125gwv9qqlw02silj8bnjnh4y07arrz60r31ai1vw"))
-              (patches
-               (list (search-patch "libtool-skip-tests2.patch")))))
+              (patches (search-patches "libtool-skip-tests2.patch"))))
     (build-system gnu-build-system)
     (propagated-inputs `(("m4" ,m4)))
     (native-inputs `(("m4" ,m4)
diff --git a/gnu/packages/avahi.scm b/gnu/packages/avahi.scm
index 2d480192af..5740ab2ff8 100644
--- a/gnu/packages/avahi.scm
+++ b/gnu/packages/avahi.scm
@@ -41,7 +41,7 @@
              (sha256
               (base32
                "0j5b5ld6bjyh3qhd2nw0jb84znq0wqai7fsrdzg7bpg24jdp2wl3"))
-             (patches (list (search-patch "avahi-localstatedir.patch")))))
+             (patches (search-patches "avahi-localstatedir.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags '("--with-distro=none"
diff --git a/gnu/packages/backup.scm b/gnu/packages/backup.scm
index ec95769a5e..a7b48f1154 100644
--- a/gnu/packages/backup.scm
+++ b/gnu/packages/backup.scm
@@ -61,8 +61,8 @@
       (sha256
        (base32
         "0jh79syhr8n3l81jxlwsmwm1pklb4d923m2lgqbswyavh1fqmvwb"))
-      (patches (list (search-patch "duplicity-piped-password.patch")
-                     (search-patch "duplicity-test_selection-tmp.patch")))))
+      (patches (search-patches "duplicity-piped-password.patch"
+                               "duplicity-test_selection-tmp.patch"))))
     (build-system python-build-system)
     (native-inputs
      `(("python2-setuptools" ,python2-setuptools)
@@ -146,10 +146,10 @@ backups (called chunks) to allow easy burning to CD/DVD.")
         (base32
          "0pixqnrcf35dnqgv0lp7qlcw7k13620qkhgxr288v7p4iz6ym1zb"))
        (patches
-        (list (search-patch "libarchive-mtree-filename-length-fix.patch")
-              (search-patch "libarchive-fix-lzo-test-case.patch")
-              (search-patch "libarchive-CVE-2013-0211.patch")
-              (search-patch "libarchive-bsdtar-test.patch")))))
+        (search-patches "libarchive-mtree-filename-length-fix.patch"
+                        "libarchive-fix-lzo-test-case.patch"
+                        "libarchive-CVE-2013-0211.patch"
+                        "libarchive-bsdtar-test.patch"))))
     (build-system gnu-build-system)
     ;; TODO: Add -L/path/to/nettle in libarchive.pc.
     (inputs
@@ -377,8 +377,7 @@ changes are stored.")
               (sha256
                (base32
                 "0fpdyxww41ba52d98blvnf543xvirq1v9xz1i3x1gm9lzlzpmc2g"))
-              (patches
-               (list (search-patch "diffutils-gets-undeclared.patch")))))
+              (patches (search-patches "diffutils-gets-undeclared.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("guile" ,guile-2.0)
@@ -410,13 +409,13 @@ detection, and lossless compression.")
 (define-public borg
   (package
     (name "borg")
-    (version "1.0.0")
+    (version "1.0.2")
     (source (origin
               (method url-fetch)
               (uri (pypi-uri "borgbackup" version))
               (sha256
                (base32
-                "0wa6cvqs3rni5nwrgagigchcly8a53rxk56z0zn8iaii2cqrw2sh"))))
+                "1myz10pwxnac9z59gw1w3xjhz6ghx03vngpl97ca527pj0r39shi"))))
     (build-system python-build-system)
     (arguments
      `(#:phases
diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm
index 2b491aa17c..fce193ceec 100644
--- a/gnu/packages/base.scm
+++ b/gnu/packages/base.scm
@@ -82,8 +82,7 @@ command-line arguments, multiple languages, and so on.")
             (sha256
              (base32
               "0c38b67cnwchwzv4wq2gpz6smkhdxrac2hhssv8f0l04qnx867p2"))
-            (patches
-             (list (search-patch "grep-timing-sensitive-test.patch")))))
+            (patches (search-patches "grep-timing-sensitive-test.patch"))))
    (build-system gnu-build-system)
    (native-inputs `(("perl" ,perl)))             ;some of the tests require it
    (synopsis "Print lines matching a pattern")
@@ -109,7 +108,7 @@ including, for example, recursive directory searching.")
             (sha256
              (base32
               "1myvrmh99jsvk7v3d7crm0gcrq51hmmm1r2kjyyci152in1x2j7h"))
-            (patches (list (search-patch "sed-hurd-path-max.patch")))))
+            (patches (search-patches "sed-hurd-path-max.patch"))))
    (build-system gnu-build-system)
    (synopsis "Stream editor")
    (arguments
@@ -145,9 +144,8 @@ implementation offers several extensions over the standard utility.")
             (sha256
              (base32
               "1wi2zwm4c9r3h3b8y4w0nm0qq897kn8kyj9k22ba0iqvxj48vvk4"))
-            (patches (map search-patch
-                          '("tar-d_ino_in_dirent-fix.patch"
-                            "tar-skip-unreliable-tests.patch")))))
+            (patches (search-patches "tar-d_ino_in_dirent-fix.patch"
+                                     "tar-skip-unreliable-tests.patch"))))
    (build-system gnu-build-system)
    (synopsis "Managing tar archives")
    (description
@@ -171,7 +169,7 @@ standard utility.")
               (sha256
                (base32
                 "16d2r9kpivaak948mxzc0bai45mqfw73m113wrkmbffnalv1b5gx"))
-              (patches (list (search-patch "patch-hurd-path-max.patch")))))
+              (patches (search-patches "patch-hurd-path-max.patch"))))
    (build-system gnu-build-system)
    (native-inputs `(("ed" ,ed)))
    (synopsis "Apply differences to originals, with optional backups")
@@ -217,9 +215,8 @@ interactive means to merge two files.")
             (sha256
              (base32
               "178nn4dl7wbcw499czikirnkniwnx36argdnqgz4ik9i6zvwkm6y"))
-            (patches (map search-patch
-                          '("findutils-localstatedir.patch"
-                            "findutils-test-xargs.patch")))))
+            (patches (search-patches "findutils-localstatedir.patch"
+                                     "findutils-test-xargs.patch"))))
    (build-system gnu-build-system)
    (arguments
     `(#:configure-flags (list
@@ -316,7 +313,7 @@ functionality beyond that which is outlined in the POSIX standard.")
             (sha256
              (base32
               "19gwwhik3wdwn0r42b7xcihkbxvjl9r2bdal8nifc3k5i4rn3iqb"))
-            (patches (list (search-patch "make-impure-dirs.patch")))))
+            (patches (search-patches "make-impure-dirs.patch"))))
    (build-system gnu-build-system)
    (native-inputs `(("pkg-config" ,pkg-config)))  ; to detect Guile
    (inputs `(("guile" ,guile-2.0)))
@@ -354,8 +351,8 @@ change.  GNU make offers many powerful extensions over the standard utility.")
             (sha256
              (base32
               "08lzmhidzc16af1zbx34f8cy4z7mzrswpdbhrb8shy3xxpflmcdm"))
-            (patches (list (search-patch "binutils-ld-new-dtags.patch")
-                           (search-patch "binutils-loongson-workaround.patch")))))
+            (patches (search-patches "binutils-ld-new-dtags.patch"
+                                     "binutils-loongson-workaround.patch"))))
    (build-system gnu-build-system)
 
    ;; TODO: Add dependency on zlib + those for Gold.
@@ -475,10 +472,9 @@ store.")
                 (("use_ldconfig=yes")
                  "use_ldconfig=no")))
             (modules '((guix build utils)))
-            (patches (map search-patch
-                          '("glibc-ldd-x86_64.patch"
-                            "glibc-versioned-locpath.patch"
-                            "glibc-o-largefile.patch")))))
+            (patches (search-patches "glibc-ldd-x86_64.patch"
+                                     "glibc-versioned-locpath.patch"
+                                     "glibc-o-largefile.patch"))))
    (build-system gnu-build-system)
 
    ;; Glibc's <limits.h> refers to <linux/limit.h>, for instance, so glibc
@@ -644,7 +640,7 @@ with the Linux kernel.")
               (sha256
                (base32
                 "1f135546j34s9bfkydmx2nhh9vwxlx60jldi80zmsnln6wj3dsxf"))
-              (patches (list (search-patch "glibc-ldd-x86_64.patch")))))))
+              (patches (search-patches "glibc-ldd-x86_64.patch"))))))
 
 (define-public glibc-locales
   (package
@@ -764,8 +760,7 @@ command.")
                (base32
                 "17gsh0kaz0zyvghjmx861mi2p65m9901lngi179x61zm6v2v3xc4"))
               (file-name (string-append name "-" version))
-              (patches (map search-patch
-                            '("glibc-hurd-extern-inline.patch")))))
+              (patches (search-patches "glibc-hurd-extern-inline.patch"))))
 
     ;; Libc provides <hurd.h>, which includes a bunch of Hurd and Mach headers,
     ;; so both should be propagated.
diff --git a/gnu/packages/bash.scm b/gnu/packages/bash.scm
index 15909c7e88..cad66da70b 100644
--- a/gnu/packages/bash.scm
+++ b/gnu/packages/bash.scm
@@ -285,7 +285,7 @@ without modification.")
                (base32
                 "0kxf8s5bw7y50x0ksb77d3kv0dwadixhybl818w27y6mlw26hq1b"))
               (patches
-               (list (search-patch "bash-completion-directories.patch")))))
+               (search-patches "bash-completion-directories.patch"))))
     (build-system gnu-build-system)
     (native-inputs `(("util-linux" ,util-linux)))
     (arguments
diff --git a/gnu/packages/bioinformatics.scm b/gnu/packages/bioinformatics.scm
index 0afc0a6979..079fd467cc 100644
--- a/gnu/packages/bioinformatics.scm
+++ b/gnu/packages/bioinformatics.scm
@@ -716,7 +716,7 @@ gapped, local, and paired-end alignment modes.")
               (sha256
                (base32
                 "168zlzykq622zbgkh90a90f1bdgsxkscq2zxzbj8brq80hbjpyp7"))
-              (patches (list (search-patch "tophat-build-with-later-seqan.patch")))
+              (patches (search-patches "tophat-build-with-later-seqan.patch"))
               (modules '((guix build utils)))
               (snippet
                '(begin
@@ -922,6 +922,75 @@ also includes an interface for tabix.")
 (define-public python2-pysam
   (package-with-python2 python-pysam))
 
+(define-public python-twobitreader
+  (package
+    (name "python-twobitreader")
+    (version "3.1.2")
+    (source (origin
+              (method url-fetch)
+              (uri (pypi-uri "twobitreader" version))
+              (sha256
+               (base32
+                "0y408fp6psqzwxpcpqn0wp7fr41dwz8d54wpj6j261fj5q8vs169"))))
+    (properties `((python2-variant . ,(delay python2-twobitreader))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-sphinx" ,python-sphinx)))
+    (home-page "https://github.com/benjschiller/twobitreader")
+    (synopsis "Python library for reading .2bit files")
+    (description
+     "twobitreader is a Python library for reading .2bit files as used by the
+UCSC genome browser.")
+    (license license:artistic2.0)))
+
+(define-public python2-twobitreader
+  (let ((base (package-with-python2 (strip-python2-variant python-twobitreader))))
+    (package
+      (inherit base)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs base))))))
+
+(define-public python-plastid
+  (package
+    (name "python-plastid")
+    (version "0.4.5")
+    (source (origin
+              (method url-fetch)
+              (uri (pypi-uri "plastid" version))
+              (sha256
+               (base32
+                "1nhxw8a5gn9as58i2ih52c5cjwj48ik418pzsjwph3s66mmy9yvq"))))
+    (properties `((python2-variant . ,(delay python2-plastid))))
+    (build-system python-build-system)
+    (arguments
+     ;; Some test files are not included.
+     `(#:tests? #f))
+    (propagated-inputs
+     `(("python-numpy" ,python-numpy)
+       ("python-scipy" ,python-scipy)
+       ("python-pandas" ,python-pandas)
+       ("python-pysam" ,python-pysam)
+       ("python-matplotlib" ,python-matplotlib)
+       ("python-biopython" ,python-biopython)
+       ("python-twobitreader" ,python-twobitreader)))
+    (native-inputs
+     `(("python-cython" ,python-cython)
+       ("python-nose" ,python-nose)))
+    (home-page "https://github.com/joshuagryphon/plastid")
+    (synopsis "Python library for genomic analysis")
+    (description
+     "plastid is a Python library for genomic analysis – in particular,
+high-throughput sequencing data – with an emphasis on simplicity.")
+    (license license:bsd-3)))
+
+(define-public python2-plastid
+  (let ((base (package-with-python2 (strip-python2-variant python-plastid))))
+    (package
+      (inherit base)
+      ;; setuptools is required at runtime
+      (propagated-inputs `(("python2-setuptools" ,python2-setuptools)
+                           ,@(package-propagated-inputs base))))))
+
 (define-public cd-hit
   (package
     (name "cd-hit")
@@ -1156,8 +1225,7 @@ time.")
                 "07y179f63d7qnzdvkqcziwk9bs3k4zhp81q392fp1hwszjdvy22f"))
               ;; This patch has been sent upstream already and is available
               ;; for download from Sourceforge, but it has not been merged.
-              (patches (list
-                        (search-patch "crossmap-allow-system-pysam.patch")))
+              (patches (search-patches "crossmap-allow-system-pysam.patch"))
               (modules '((guix build utils)))
               ;; remove bundled copy of pysam
               (snippet
@@ -2076,9 +2144,9 @@ HMMs).")
 from high-throughput sequencing assays.")
     (license license:gpl3+)))
 
-(define-public htsjdk
+(define-public java-htsjdk
   (package
-    (name "htsjdk")
+    (name "java-htsjdk")
     (version "1.129")
     (source (origin
               (method url-fetch)
@@ -2480,6 +2548,41 @@ RNA-Seq, the MISO model uses Bayesian inference to compute the probability
 that a read originated from a particular isoform.")
     (license license:gpl2)))
 
+(define-public muscle
+  (package
+    (name "muscle")
+    (version "3.8.1551")
+    (source (origin
+              (method url-fetch/tarbomb)
+              (file-name (string-append name "-" version))
+              (uri (string-append
+                    "http://www.drive5.com/muscle/muscle_src_"
+                    version ".tar.gz"))
+              (sha256
+               (base32
+                "0bj8kj7sdizy3987zx6w7axihk40fk8rn76mpbqqjcnd64i5a367"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:make-flags (list "LDLIBS = -lm")
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)
+         (replace 'check
+           ;; There are no tests, so just test if it runs.
+           (lambda _ (zero? (system* "./muscle" "-version"))))
+         (replace 'install
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin")))
+               (install-file "muscle" bin)))))))
+    (home-page "http://www.drive5.com/muscle")
+    (synopsis "Multiple sequence alignment program")
+    (description
+     "MUSCLE aims to be a fast and accurate multiple sequence alignment
+program for nucleotide and protein sequences.")
+    ;; License information found in 'muscle -h' and usage.cpp.
+    (license license:public-domain)))
+
 (define-public orfm
   (package
     (name "orfm")
@@ -2722,7 +2825,7 @@ partial genes, and identifies translation initiation sites.")
                        version ".tar.gz"))
        (sha256
         (base32 "0nzdc0j0hjllhsd5f2xli95dafm3nawskigs140xzvjk67xh0r9q"))
-       (patches (list (search-patch "rsem-makefile.patch")))
+       (patches (search-patches "rsem-makefile.patch"))
        (modules '((guix build utils)))
        (snippet
         '(begin
@@ -2834,7 +2937,7 @@ distribution, coverage uniformity, strand specificity, etc.")
 (define-public samtools
   (package
     (name "samtools")
-    (version "1.3")
+    (version "1.3.1")
     (source
      (origin
        (method url-fetch)
@@ -2843,7 +2946,7 @@ distribution, coverage uniformity, strand specificity, etc.")
                        version "/samtools-" version ".tar.bz2"))
        (sha256
         (base32
-         "03mnf0mhbfwhqlqfslrhfnw68s3g0fs1as354i9a584mqw1l1smy"))))
+         "0znnnxc467jbf1as2dpskrjhfh8mbll760j6w6rdkwlwbqsp8gbc"))))
     (build-system gnu-build-system)
     (arguments
      `(#:modules ((ice-9 ftw)
@@ -3013,9 +3116,9 @@ any particular back-end implementation, and supports use of multiple back-ends
 simultaneously.")
     (license license:public-domain)))
 
-(define-public ngs-java
+(define-public java-ngs
   (package (inherit ngs-sdk)
-    (name "ngs-java")
+    (name "java-ngs")
     (arguments
      `(,@(substitute-keyword-arguments
              `(#:modules ((guix build gnu-build-system)
@@ -3078,7 +3181,7 @@ simultaneously.")
                     (string-append "--with-ngs-sdk-prefix="
                                    (assoc-ref inputs "ngs-sdk"))
                     (string-append "--with-ngs-java-prefix="
-                                   (assoc-ref inputs "ngs-java"))
+                                   (assoc-ref inputs "java-ngs"))
                     (string-append "--with-hdf5-prefix="
                                    (assoc-ref inputs "hdf5"))))))
         (alist-cons-after
@@ -3104,7 +3207,7 @@ simultaneously.")
     (inputs
      `(("libxml2" ,libxml2)
        ("ngs-sdk" ,ngs-sdk)
-       ("ngs-java" ,ngs-java)
+       ("java-ngs" ,java-ngs)
        ("libmagic" ,file)
        ("hdf5" ,hdf5)))
     (native-inputs `(("perl" ,perl)))
@@ -3129,7 +3232,7 @@ accessed/downloaded on demand across HTTP.")
              version "-src.zip"))
        (sha256
         (base32 "0as8gxm4pjyc8dxmm1sl873rrd7wn5qs0l29nqfnl31x8i467xaa"))
-       (patches (list (search-patch "plink-1.07-unclobber-i.patch")))))
+       (patches (search-patches "plink-1.07-unclobber-i.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:tests? #f ;no "check" target
@@ -3889,13 +3992,13 @@ BLAST, KEGG, GenBank, MEDLINE and GO.")
 (define-public r-acsnminer
   (package
     (name "r-acsnminer")
-    (version "0.15.11")
+    (version "0.16.01.29")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "ACSNMineR" version))
               (sha256
                (base32
-                "1dl4drhjyazwm9wxlm8yfppwvvj4h6jxwmz8kfw5bxpb3jdnsqvy"))))
+                "1b1243wkncanm1blkqzicjgzb576vzcg4iwinsgn2xqr7f264amf"))))
     (properties `((upstream-name . "ACSNMineR")))
     (build-system r-build-system)
     (propagated-inputs
@@ -4036,6 +4139,38 @@ translation between different chromosome sequence naming conventions (e.g.,
 names in their natural, rather than lexicographic, order.")
     (license license:artistic2.0)))
 
+(define-public r-variantannotation
+  (package
+    (name "r-variantannotation")
+    (version "1.16.4")
+    (source (origin
+              (method url-fetch)
+              (uri (bioconductor-uri "VariantAnnotation" version))
+              (sha256
+               (base32
+                "1z42j3p9b8h725inq8n0230llsdbav3gwcxy1nliypzfkxbzahsb"))))
+    (properties
+     `((upstream-name . "VariantAnnotation")))
+    (inputs
+     `(("zlib" ,zlib)))
+    (propagated-inputs
+     `(("r-annotationdbi" ,r-annotationdbi)
+       ("r-biocgenerics" ,r-biocgenerics)
+       ("r-bsgenome" ,r-bsgenome)
+       ("r-dbi" ,r-dbi)
+       ("r-genomeinfodb" ,r-genomeinfodb)
+       ("r-genomicfeatures" ,r-genomicfeatures)
+       ("r-genomicranges" ,r-genomicranges)
+       ("r-summarizedexperiment" ,r-summarizedexperiment)
+       ("r-rsamtools" ,r-rsamtools)
+       ("r-zlibbioc" ,r-zlibbioc)))
+    (build-system r-build-system)
+    (home-page "https://bioconductor.org/packages/VariantAnnotation")
+    (synopsis "Package for annotation of genetic variants")
+    (description "This R package can annotate variants, compute amino acid
+coding changes and predict coding outcomes.")
+    (license license:artistic2.0)))
+
 (define-public r-xvector
   (package
     (name "r-xvector")
@@ -4716,10 +4851,184 @@ annotations for the genome of the model fruit fly Drosophila melanogaster.")
 annotations for the genome of the model mouse Mus musculus.")
     (license license:artistic2.0)))
 
+(define-public r-seqlogo
+  (package
+    (name "r-seqlogo")
+    (version "1.36.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (bioconductor-uri "seqLogo" version))
+       (sha256
+        (base32
+         "0kn1a1nf2j4v9c09vjkz9bmxlln7yhg87bnyrdsxy1m55x56rn5k"))))
+    (properties `((upstream-name . "seqLogo")))
+    (build-system r-build-system)
+    (home-page "http://bioconductor.org/packages/seqLogo")
+    (synopsis "Sequence logos for DNA sequence alignments")
+    (description
+     "seqLogo takes the position weight matrix of a DNA sequence motif and
+plots the corresponding sequence logo as introduced by Schneider and
+Stephens (1990).")
+    (license license:lgpl2.0+)))
+
+(define-public r-bsgenome-hsapiens-ucsc-hg19
+  (package
+    (name "r-bsgenome-hsapiens-ucsc-hg19")
+    (version "1.4.0")
+    (source (origin
+              (method url-fetch)
+              ;; We cannot use bioconductor-uri here because this tarball is
+              ;; located under "data/annotation/" instead of "bioc/".
+              (uri (string-append "http://www.bioconductor.org/packages/"
+                                  "release/data/annotation/src/contrib/"
+                                  "BSgenome.Hsapiens.UCSC.hg19_"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "1y0nqpk8cw5a34sd9hmin3z4v7iqm6hf6l22cl81vlbxqbjibxc8"))))
+    (properties
+     `((upstream-name . "BSgenome.Hsapiens.UCSC.hg19")))
+    (build-system r-build-system)
+    ;; As this package provides little more than a very large data file it
+    ;; doesn't make sense to build substitutes.
+    (arguments `(#:substitutable? #f))
+    (propagated-inputs
+     `(("r-bsgenome" ,r-bsgenome)))
+    (home-page
+     "http://www.bioconductor.org/packages/BSgenome.Hsapiens.UCSC.hg19/")
+    (synopsis "Full genome sequences for Homo sapiens")
+    (description
+     "This package provides full genome sequences for Homo sapiens as provided
+by UCSC (hg19, February 2009) and stored in Biostrings objects.")
+    (license license:artistic2.0)))
+
+(define-public r-bsgenome-mmusculus-ucsc-mm9
+  (package
+    (name "r-bsgenome-mmusculus-ucsc-mm9")
+    (version "1.4.0")
+    (source (origin
+              (method url-fetch)
+              ;; We cannot use bioconductor-uri here because this tarball is
+              ;; located under "data/annotation/" instead of "bioc/".
+              (uri (string-append "http://www.bioconductor.org/packages/"
+                                  "release/data/annotation/src/contrib/"
+                                  "BSgenome.Mmusculus.UCSC.mm9_"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "1birqw30g2azimxpnjfzmkphan7x131yy8b9h85lfz5fjdg7841i"))))
+    (properties
+     `((upstream-name . "BSgenome.Mmusculus.UCSC.mm9")))
+    (build-system r-build-system)
+    ;; As this package provides little more than a very large data file it
+    ;; doesn't make sense to build substitutes.
+    (arguments `(#:substitutable? #f))
+    (propagated-inputs
+     `(("r-bsgenome" ,r-bsgenome)))
+    (home-page
+     "http://www.bioconductor.org/packages/BSgenome.Mmusculus.UCSC.mm9/")
+    (synopsis "Full genome sequences for Mouse")
+    (description
+     "This package provides full genome sequences for Mus musculus (Mouse) as
+provided by UCSC (mm9, July 2007) and stored in Biostrings objects.")
+    (license license:artistic2.0)))
+
+(define-public r-bsgenome-celegans-ucsc-ce6
+  (package
+    (name "r-bsgenome-celegans-ucsc-ce6")
+    (version "1.4.0")
+    (source (origin
+              (method url-fetch)
+              ;; We cannot use bioconductor-uri here because this tarball is
+              ;; located under "data/annotation/" instead of "bioc/".
+              (uri (string-append "http://www.bioconductor.org/packages/"
+                                  "release/data/annotation/src/contrib/"
+                                  "BSgenome.Celegans.UCSC.ce6_"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "0mqzb353xv2c3m3vkb315dkmnxkgczp7ndnknyhpgjlybyf715v9"))))
+    (properties
+     `((upstream-name . "BSgenome.Celegans.UCSC.ce6")))
+    (build-system r-build-system)
+    ;; As this package provides little more than a very large data file it
+    ;; doesn't make sense to build substitutes.
+    (arguments `(#:substitutable? #f))
+    (propagated-inputs
+     `(("r-bsgenome" ,r-bsgenome)))
+    (home-page
+     "http://www.bioconductor.org/packages/BSgenome.Celegans.UCSC.ce6/")
+    (synopsis "Full genome sequences for Worm")
+    (description
+     "This package provides full genome sequences for Caenorhabditis
+elegans (Worm) as provided by UCSC (ce6, May 2008) and stored in Biostrings
+objects.")
+    (license license:artistic2.0)))
+
+(define-public r-bsgenome-dmelanogaster-ucsc-dm3
+  (package
+    (name "r-bsgenome-dmelanogaster-ucsc-dm3")
+    (version "1.4.0")
+    (source (origin
+              (method url-fetch)
+              ;; We cannot use bioconductor-uri here because this tarball is
+              ;; located under "data/annotation/" instead of "bioc/".
+              (uri (string-append "http://www.bioconductor.org/packages/"
+                                  "release/data/annotation/src/contrib/"
+                                  "BSgenome.Dmelanogaster.UCSC.dm3_"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "19bm3lkhhkag3gnwp419211fh0cnr0x6fa0r1lr0ycwrikxdxsv8"))))
+    (properties
+     `((upstream-name . "BSgenome.Dmelanogaster.UCSC.dm3")))
+    (build-system r-build-system)
+    ;; As this package provides little more than a very large data file it
+    ;; doesn't make sense to build substitutes.
+    (arguments `(#:substitutable? #f))
+    (propagated-inputs
+     `(("r-bsgenome" ,r-bsgenome)))
+    (home-page
+     "http://www.bioconductor.org/packages/BSgenome.Dmelanogaster.UCSC.dm3/")
+    (synopsis "Full genome sequences for Fly")
+    (description
+     "This package provides full genome sequences for Drosophila
+melanogaster (Fly) as provided by UCSC (dm3, April 2006) and stored in
+Biostrings objects.")
+    (license license:artistic2.0)))
+
+(define-public r-motifrg
+  (package
+    (name "r-motifrg")
+    (version "1.14.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (bioconductor-uri "motifRG" version))
+       (sha256
+        (base32
+         "1v9zm5629k2lcqbbgw8bwflvbircyxkfavbkvmbd212kgwcng8vn"))))
+    (properties `((upstream-name . "motifRG")))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-biostrings" ,r-biostrings)
+       ("r-bsgenome" ,r-bsgenome)
+       ("r-bsgenome.hsapiens.ucsc.hg19" ,r-bsgenome-hsapiens-ucsc-hg19)
+       ("r-iranges" ,r-iranges)
+       ("r-seqlogo" ,r-seqlogo)
+       ("r-xvector" ,r-xvector)))
+    (home-page "http://bioconductor.org/packages/motifRG")
+    (synopsis "Discover motifs in high throughput sequencing data")
+    (description
+     "This package provides tools for discriminative motif discovery in high
+throughput genetic sequencing data sets using regression methods.")
+    (license license:artistic2.0)))
+
 (define-public r-qtl
  (package
   (name "r-qtl")
-  (version "1.38-4")
+  (version "1.39-5")
   (source
    (origin
     (method url-fetch)
@@ -4727,7 +5036,7 @@ annotations for the genome of the model mouse Mus musculus.")
                         version ".tar.gz"))
     (sha256
      (base32
-      "0rv9xhp8lyldpgwxqirhyjqvg07dr5x4x1x2jpyj37dada9ccyx3"))))
+      "1grwgvyv7x0dgay1858bg7qf4wk47gpnq7qkqpcda9cn0h970d6f"))))
   (build-system r-build-system)
   (home-page "http://rqtl.org/")
   (synopsis "R package for analyzing QTL experiments in genetics")
@@ -4741,6 +5050,25 @@ identify genotyping errors, and to perform single-QTL and two-QTL,
 two-dimensional genome scans.")
   (license license:gpl3)))
 
+(define-public r-zlibbioc
+  (package
+    (name "r-zlibbioc")
+    (version "1.16.0")
+    (source (origin
+              (method url-fetch)
+              (uri (bioconductor-uri "zlibbioc" version))
+              (sha256
+               (base32
+                "01wc26ndg4jsn1wyrl6zzq636gxaip5fci0xapym4lh9wryc4wnw"))))
+    (properties
+     `((upstream-name . "zlibbioc")))
+    (build-system r-build-system)
+    (home-page "https://bioconductor.org/packages/zlibbioc")
+    (synopsis "Provider for zlib-1.2.5 to R packages")
+    (description "This package uses the source code of zlib-1.2.5 to create
+libraries for systems that do not have these available via other means.")
+    (license license:artistic2.0)))
+
 (define-public pepr
   (package
     (name "pepr")
@@ -4781,3 +5109,31 @@ negative binomial distribution to model the read counts among the samples in
 the same group, and look for consistent differences between ChIP and control
 group or two ChIP groups run under different conditions.")
     (license license:gpl3+)))
+
+(define-public filevercmp
+  (let ((commit "1a9b779b93d0b244040274794d402106907b71b7"))
+    (package
+      (name "filevercmp")
+      (version (string-append "0-1." (string-take commit 7)))
+      (source (origin
+        (method url-fetch)
+        (uri (string-append "https://github.com/ekg/filevercmp/archive/"
+                            commit ".tar.gz"))
+        (file-name (string-append name "-" version ".tar.gz"))
+        (sha256
+         (base32 "0yp5jswf5j2pqc6517x277s4s6h1ss99v57kxw9gy0jkfl3yh450"))))
+      (build-system gnu-build-system)
+      (arguments
+       `(#:tests? #f ; There are no tests to run.
+         #:phases
+         (modify-phases %standard-phases
+           (delete 'configure) ; There is no configure phase.
+           (replace 'install
+             (lambda* (#:key outputs #:allow-other-keys)
+               (let ((bin (string-append (assoc-ref outputs "out") "/bin")))
+                 (install-file "filevercmp" bin)))))))
+      (home-page "https://github.com/ekg/filevercmp")
+      (synopsis "This program compares version strings")
+      (description "This program compares version strings.  It intends to be a
+replacement for strverscmp.")
+      (license license:gpl3+))))
diff --git a/gnu/packages/bittorrent.scm b/gnu/packages/bittorrent.scm
index 26b0fc6fdc..d8252c8b37 100644
--- a/gnu/packages/bittorrent.scm
+++ b/gnu/packages/bittorrent.scm
@@ -207,7 +207,7 @@ interface, for the Transmission BitTorrent daemon.")
 (define-public aria2
   (package
     (name "aria2")
-    (version "1.21.0")
+    (version "1.22.0")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://github.com/tatsuhiro-t/aria2/"
@@ -215,7 +215,7 @@ interface, for the Transmission BitTorrent daemon.")
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
-                "1035rzx9y7qv4p7cv04f461343dxha7ikprch059x2fci8n5yp12"))))
+                "12agwdvvkr34wqhyyfp418dj0k7nbr297qmcd3wj5kkn7brv6gxc"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags '("--enable-libaria2")
diff --git a/gnu/packages/bootstrap.scm b/gnu/packages/bootstrap.scm
index 2cd8534ace..2aa4711ba8 100644
--- a/gnu/packages/bootstrap.scm
+++ b/gnu/packages/bootstrap.scm
@@ -125,7 +125,7 @@ successful, or false to signal an error."
        ("tarball" ,(bootstrap-origin (source (%current-system))))))
     (source #f)
     (synopsis description)
-    (description #f)
+    (description description)
     (home-page #f)
     (license gpl3+)))
 
@@ -166,11 +166,13 @@ successful, or false to signal an error."
         ((string=? system "mips64el-linux") "/lib/ld.so.1")
         ((string=? system "i586-gnu") "/lib/ld.so.1")
         ((string=? system "i686-gnu") "/lib/ld.so.1")
+        ((string=? system "aarch64-linux") "/lib/ld-linux-aarch64.so.1")
 
         ;; XXX: This one is used bare-bones, without a libc, so add a case
         ;; here just so we can keep going.
         ((string=? system "xtensa-elf") "no-ld.so")
         ((string=? system "avr") "no-ld.so")
+        ((string=? system "i686-mingw") "no-ld.so")
 
         (else (error "dynamic linker name not known for this system"
                      system))))
@@ -410,7 +412,7 @@ $out/bin/guile --version~%"
                          (base32
                           "0k97a3whzx3apsi9n2cbsrr79ad6lh00klxph9hw4fqyp1abkdsg")))))))))
     (synopsis "Bootstrap binaries and headers of the GNU C Library")
-    (description #f)
+    (description synopsis)
     (home-page #f)
     (license lgpl2.1+)))
 
@@ -495,7 +497,7 @@ exec ~a/bin/.gcc-wrapped -B~a/lib \
             (variable "LIBRARY_PATH")
             (files '("lib" "lib64")))))
     (synopsis "Bootstrap binaries of the GNU Compiler Collection")
-    (description #f)
+    (description synopsis)
     (home-page #f)
     (license gpl3+)))
 
diff --git a/gnu/packages/c.scm b/gnu/packages/c.scm
new file mode 100644
index 0000000000..e8d1236eb1
--- /dev/null
+++ b/gnu/packages/c.scm
@@ -0,0 +1,127 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2016 Ludovic Courtès <ludo@gnu.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 Guix 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages c)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (guix packages)
+  #:use-module (guix download)
+  #:use-module (guix build-system gnu)
+  #:use-module (guix build-system trivial)
+  #:use-module (gnu packages bootstrap)
+  #:use-module (gnu packages perl)
+  #:use-module (gnu packages texinfo)
+  #:use-module (gnu packages guile))
+
+(define-public tcc
+  (package
+    (name "tcc")                                  ;aka. "tinycc"
+    (version "0.9.26")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://savannah/tinycc/tcc-"
+                                  version ".tar.bz2"))
+              (sha256
+               (base32
+                "0wbdbdq6090ayw8bxnbikiv989kykff3m5rzbia05hrnwhd707jj"))))
+    (build-system gnu-build-system)
+    (native-inputs `(("perl" ,perl)
+                     ("texinfo" ,texinfo)))
+    (arguments
+     `(#:configure-flags (list (string-append "--elfinterp="
+                                              (assoc-ref %build-inputs "libc")
+                                              ,(glibc-dynamic-linker))
+                               (string-append "--crtprefix="
+                                              (assoc-ref %build-inputs "libc")
+                                              "/lib")
+                               (string-append "--sysincludepaths="
+                                              (assoc-ref %build-inputs "libc")
+                                              "/include:"
+                                              (assoc-ref %build-inputs
+                                                         "linux-headers")
+                                              "/include:{B}/include")
+                               (string-append "--libpaths="
+                                              (assoc-ref %build-inputs "libc")
+                                              "/lib"))
+       #:test-target "test"))
+    (synopsis "Tiny and fast C compiler")
+    (description
+     "TCC, also referred to as \"TinyCC\", is a small and fast C compiler
+written in C.  It supports ANSI C with GNU and extensions and most of the C99
+standard.")
+    (home-page "http://www.tinycc.org/")
+    (license license:lgpl2.1+)))
+
+(define-public tcc-wrapper
+  (package
+    (inherit tcc)
+    (name "tcc-wrapper")
+    (build-system trivial-build-system)
+    (native-inputs '())
+    (inputs `(("tcc" ,tcc)
+              ("guile" ,guile-2.0)))
+
+    ;; By default TCC does not honor any search path environment variable.
+    ;; This wrapper adds them.
+    ;;
+    ;; FIXME: TCC includes its own linker so our 'ld-wrapper' hack to set the
+    ;; RUNPATH is ineffective here.  We should modify TCC itself.
+    (native-search-paths
+     (list (search-path-specification
+            (variable "TCC_CPATH")
+            (files '("include")))
+           (search-path-specification
+            (variable "TCC_LIBRARY_PATH")
+            (files '("lib" "lib64")))))
+
+    (arguments
+     '(#:builder
+       (let* ((out   (assoc-ref %outputs "out"))
+              (bin   (string-append out "/bin"))
+              (tcc   (assoc-ref %build-inputs "tcc"))
+              (guile (assoc-ref %build-inputs "guile")))
+         (mkdir out)
+         (mkdir bin)
+         (call-with-output-file (string-append bin "/cc")
+           (lambda (port)
+             (format port "#!~a/bin/guile --no-auto-compile~%!#~%" guile)
+             (write
+              `(begin
+                 (use-modules (ice-9 match)
+                              (srfi srfi-26))
+
+                 (define (split path)
+                   (string-tokenize path (char-set-complement
+                                          (char-set #\:))))
+
+                 (apply execl ,(string-append tcc "/bin/tcc")
+                        ,(string-append tcc "/bin/tcc") ;argv[0]
+                        (append (cdr (command-line))
+                                (match (getenv "TCC_CPATH")
+                                  (#f '())
+                                  (str
+                                   (map (cut string-append "-I" <>)
+                                        (split str))))
+                                (match (getenv "TCC_LIBRARY_PATH")
+                                  (#f '())
+                                  (str
+                                   (map (cut string-append "-L" <>)
+                                        (split str)))))))
+              port)
+             (chmod port #o777)))
+         #t)))
+    (synopsis "Wrapper providing the 'cc' command for TCC")))
diff --git a/gnu/packages/cdrom.scm b/gnu/packages/cdrom.scm
index 46a5b234aa..4eff2d5cb0 100644
--- a/gnu/packages/cdrom.scm
+++ b/gnu/packages/cdrom.scm
@@ -164,7 +164,7 @@ files.")
              (sha256
               (base32
                "1pv4zrajm46za0f6lv162iqffih57a8ly4pc69f7y0gfyigb8p80"))
-             (patches (list (search-patch "cdparanoia-fpic.patch")))
+             (patches (search-patches "cdparanoia-fpic.patch"))
              (modules '((guix build utils)))
              (snippet
               ;; Make libraries respect LDFLAGS.
diff --git a/gnu/packages/ci.scm b/gnu/packages/ci.scm
index 5ab03c7652..be18ebd29f 100644
--- a/gnu/packages/ci.scm
+++ b/gnu/packages/ci.scm
@@ -52,10 +52,10 @@
                 (sha256
                  (base32
                   "08vc76xb7f42hh65j7qvjf58hw36aki5ml343170pq94vk75b1nh"))
-                (patches (map search-patch
-                              '("hydra-automake-1.15.patch"
-                                ;; TODO: Remove once we have a darcs input
-                                "hydra-disable-darcs-test.patch")))))
+                (patches (search-patches
+                          "hydra-automake-1.15.patch"
+                          ;; TODO: Remove once we have a darcs input
+                          "hydra-disable-darcs-test.patch"))))
       (build-system gnu-build-system)
       (native-inputs
        `(("unzip" ,unzip)
diff --git a/gnu/packages/cmake.scm b/gnu/packages/cmake.scm
index e8b292f862..cac059ec37 100644
--- a/gnu/packages/cmake.scm
+++ b/gnu/packages/cmake.scm
@@ -46,7 +46,7 @@
              (sha256
               (base32
                "1yly38mpk2s08b4rglp9xcw5pxalk0whp9hrcg7j8qpxlkc3mj4j"))
-             (patches (list (search-patch "cmake-fix-tests.patch")))))
+             (patches (search-patches "cmake-fix-tests.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:test-target "test"
diff --git a/gnu/packages/compression.scm b/gnu/packages/compression.scm
index 8508c617e1..e5cacf5ca7 100644
--- a/gnu/packages/compression.scm
+++ b/gnu/packages/compression.scm
@@ -3,12 +3,13 @@
 ;;; Copyright © 2013 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
-;;; Copyright © 2015 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2015, 2016 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Leo Famulari <leo@famulari.name>
 ;;; Copyright © 2015 Jeff Mickey <j@codemac.net>
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 Ben Woodcroft <donttrustben@gmail.com>
+;;; Copyright © 2016 Danny Milosavljevic <dannym@scratchpost.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -33,6 +34,7 @@
   #:use-module (guix git-download)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system perl)
+  #:use-module (gnu packages autotools)
   #:use-module (gnu packages backup)
   #:use-module (gnu packages base)
   #:use-module (gnu packages perl)
@@ -688,3 +690,68 @@ a collection of smaller blocks which makes random access to the original data
 possible and can compress in parallel.  This is especially useful for large
 tarballs.")
     (license license:bsd-2)))
+
+(define-public brotli
+  (let ((commit "e992cce7a174d6e2b3486616499d26bb0bad6448")
+        (revision "1"))
+    (package
+      (name "brotli")
+      (version (string-append "0.1-" revision "."
+                              (string-take commit 7)))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url "https://github.com/bagder/libbrotli.git")
+                      (commit commit)
+                      (recursive? #t)))
+                (file-name (string-append name "-" version ".tar.xz"))
+                (sha256
+                 (base32
+                  "1qxxsasvwbbbh6dl3138y9h3fg0q2v7xdk5jjc690bdg7g1wrj6n"))
+                (modules '((guix build utils)))
+                (snippet
+                 ;; This is a recursive submodule that is unnecessary for this
+                 ;; package, so delete it.
+                 '(delete-file-recursively "brotli/terryfy"))))
+      (build-system gnu-build-system)
+      (native-inputs
+       `(("autoconf" ,autoconf)
+         ("automake" ,automake)
+         ("libtool" ,libtool)))
+      (arguments
+       `(#:phases (modify-phases %standard-phases
+                    (add-after 'unpack 'autogen
+                      (lambda _
+                        (mkdir "m4")
+                        (zero? (system* "autoreconf" "-vfi")))))))
+      (home-page "https://github.com/bagder/libbrotli/")
+      (synopsis "Implementation of the Brotli compression algorithm")
+      (description
+       "Brotli is a general-purpose lossless compression algorithm.  It is
+similar in speed to deflate but offers denser compression.  This package
+provides encoder and a decoder libraries: libbrotlienc and libbrotlidec,
+respectively, based on the reference implementation from Google.")
+      (license license:expat))))
+
+(define-public cabextract
+ (package
+   (name "cabextract")
+   (version "1.6")
+   (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "http://cabextract.org.uk/cabextract-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1ysmmz25fjghq7mxb2anyyvr1ljxqxzi4piwjhk0sdamcnsn3rnf"))))
+    (build-system gnu-build-system)
+    (arguments '(#:configure-flags '("--with-external-libmspack")))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (inputs
+     `(("libmspack" ,libmspack)))
+    (home-page "http://www.cabextract.org.uk/")
+    (synopsis "Tool to unpack Cabinet archives")
+    (description "Extracts files out of Microsoft Cabinet (.cab) archives")
+    ;; Some source files specify gpl2+, lgpl2+, however COPYING is gpl3.
+    (license license:gpl3+)))
diff --git a/gnu/packages/cpio.scm b/gnu/packages/cpio.scm
index e8eede6524..77a0c82d2e 100644
--- a/gnu/packages/cpio.scm
+++ b/gnu/packages/cpio.scm
@@ -36,7 +36,7 @@
              (sha256
               (base32
                "0vi9q475h1rki53100zml75vxsykzyhrn70hidy41s5c2rc8r6bh"))
-             (patches (list (search-patch "cpio-CVE-2016-2037.patch")))))
+             (patches (search-patches "cpio-CVE-2016-2037.patch"))))
     (build-system gnu-build-system)
     (home-page "https://www.gnu.org/software/cpio/")
     (synopsis "Manage cpio and tar file archives")
diff --git a/gnu/packages/cross-base.scm b/gnu/packages/cross-base.scm
index 8bd599c25a..aa67d21c19 100644
--- a/gnu/packages/cross-base.scm
+++ b/gnu/packages/cross-base.scm
@@ -201,7 +201,7 @@ may be either a libc package or #f.)"
   "Return GCC patches needed for TARGET."
   (cond ((string-prefix? "xtensa-" target)
          ;; Patch by Qualcomm needed to build the ath9k-htc firmware.
-         (list (search-patch "ath9k-htc-firmware-gcc.patch")))
+         (search-patches "ath9k-htc-firmware-gcc.patch"))
         (else '())))
 
 (define* (cross-gcc target
diff --git a/gnu/packages/cups.scm b/gnu/packages/cups.scm
index ff3d1528c6..8437170bfa 100644
--- a/gnu/packages/cups.scm
+++ b/gnu/packages/cups.scm
@@ -1,7 +1,8 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
-;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Danny Milosavljevic <dannym@scratchpost.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -26,6 +27,10 @@
   #:use-module (gnu packages)
   #:use-module (gnu packages avahi)
   #:use-module (gnu packages compression)
+  #:use-module (gnu packages libusb)
+  #:use-module (gnu packages autotools)
+  #:use-module (gnu packages python)
+  #:use-module (gnu packages scanner)
   #:use-module (gnu packages image)
   #:use-module (gnu packages fonts) ;font-dejavu
   #:use-module (gnu packages fontutils)
@@ -297,3 +302,113 @@ device-specific programs to convert and print many types of files.")
        ("gnutls" ,gnutls)
        ("cups-filters" ,cups-filters)
        ("zlib"  ,zlib)))))
+
+(define-public hplip
+  (package
+    (name "hplip")
+    (version "3.16.3")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://sourceforge/hplip/"
+                                  "hplip-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1501qdnkjp1ybgagy5188fmf6cgmj5555ygjl3543nlbwcp31lj2"))))
+    (build-system gnu-build-system)
+    (home-page "http://hplipopensource.com/")
+    (synopsis "HP Printer Drivers")
+    (description "Hewlett-Packard Printer Drivers and PPDs.")
+
+    ;; The 'COPYING' file lists directories where each of these 3 licenses
+    ;; applies.
+    (license (list license:gpl2+ license:bsd-3 license:expat))
+
+    ;; TODO install apparmor profile files eventually.
+    (arguments
+     `(#:configure-flags
+       `("--disable-network-build"
+         ,(string-append "--prefix=" (assoc-ref %outputs "out"))
+         ,(string-append "--sysconfdir=" (assoc-ref %outputs "out") "/etc")
+         ;; Disable until mime.types merging works (FIXME).
+         "--disable-fax-build"
+         "--enable-hpcups-install"
+         "--enable-new-hpcups"
+         "--enable-cups_ppd_install"
+         "--enable-cups_drv_install"
+         ;; TODO add foomatic drv install eventually.
+         ;; TODO --enable-policykit eventually.
+         ,(string-append "--with-cupsfilterdir="
+                         (assoc-ref %outputs "out") "/lib/cups/filter")
+         ,(string-append "--with-cupsbackenddir="
+                         (assoc-ref %outputs "out") "/lib/cups/backend")
+         ,(string-append "--with-icondir="
+                         (assoc-ref %outputs "out") "/share/applications")
+         ,(string-append "--with-systraydir="
+                         (assoc-ref %outputs "out") "/etc/xdg"))
+
+       #:imported-modules ((guix build python-build-system)
+                           ,@%gnu-build-system-modules)
+       #:modules ((guix build gnu-build-system)
+                  (guix build utils)
+                  ((guix build python-build-system) #:prefix python:))
+
+       #:phases (modify-phases %standard-phases
+                  (add-after 'unpack 'fix-hard-coded-file-names
+                    (lambda* (#:key inputs outputs #:allow-other-keys)
+                      (let ((out (assoc-ref outputs "out"))
+                            ;; FIXME: use merged ppds (I think actually only
+                            ;; drvs need to be merged).
+                            (cupsdir (assoc-ref inputs "cups-minimal")))
+                        (substitute* "base/g.py"
+                          (("'/usr/share;[^']*'")
+                           (string-append "'" cupsdir "/share'"))
+                          (("'/etc/hp/hplip.conf'")
+                           (string-append "'" out
+                                          "/etc/hp/hplip.conf" "'")))
+
+                        (substitute* "Makefile.in"
+                          (("[[:blank:]]check-plugin\\.py[[:blank:]]") " ")
+                          ;; FIXME Use beginning-of-word in regexp.
+                          (("[[:blank:]]plugin\\.py[[:blank:]]") " ")
+                          (("/usr/include/libusb-1.0")
+                           (string-append (assoc-ref inputs "libusb")
+                                          "/include/libusb-1.0"))
+                          (("^\tinstall-dist_hplip_stateDATA")
+                           ;; Remove dependencies on
+                           ;; 'install-dist_hplip_stateDATA' so we don't bail
+                           ;; out while trying to create /var/lib/hplip.
+                           "\t")
+                          (("hplip_confdir = /etc/hp")
+                           ;; This is only used for installing the default config.
+                           (string-append "hplip_confdir = " out
+                                          "/etc/hp"))
+                          (("halpredir = /usr/share/hal/fdi/preprobe/10osvendor")
+                           ;; Note: We don't use hal.
+                           (string-append "halpredir = " out
+                                          "/share/hal/fdi/preprobe/10osvendor"))
+                          (("rulesdir = /etc/udev/rules.d")
+                           ;; udev rules will be merged by base service.
+                           (string-append "rulesdir = " out
+                                          "/lib/udev/rules.d"))
+                          (("rulessystemdir = /usr/lib/systemd/system")
+                           ;; We don't use systemd.
+                           (string-append "rulessystemdir = " out
+                                          "/lib/systemd/system"))
+                          (("/etc/sane.d")
+                           (string-append out "/etc/sane.d"))))))
+
+                  ;; Wrap bin/* so that the Python libs are found.
+                  (add-after 'install 'wrap-binaries
+                    (assoc-ref python:%standard-phases 'wrap)))))
+
+    ;; Python3 support is available starting from hplip@3.15.2.
+    (inputs `(("libjpeg" ,libjpeg)
+              ("cups-minimal" ,cups-minimal)
+              ("libusb" ,libusb)
+              ("sane-backends" ,sane-backends)
+              ("dbus" ,dbus)
+              ("python-wrapper" ,python-wrapper)
+              ("python" ,python)
+              ;; TODO: Make hp-setup find python-dbus.
+              ("python-dbus" ,python-dbus)))
+    (native-inputs `(("pkg-config" ,pkg-config)))))
diff --git a/gnu/packages/databases.scm b/gnu/packages/databases.scm
index 0ca6fd8986..88a784d293 100644
--- a/gnu/packages/databases.scm
+++ b/gnu/packages/databases.scm
@@ -133,7 +133,7 @@ SQL, Key/Value, XML/XQuery or Java Object storage for their data model.")
 (define-public mysql
   (package
     (name "mysql")
-    (version "5.7.11")
+    (version "5.7.12")
     (source (origin
              (method url-fetch)
              (uri (list (string-append
@@ -145,7 +145,7 @@ SQL, Key/Value, XML/XQuery or Java Object storage for their data model.")
                           name "-" version ".tar.gz")))
              (sha256
               (base32
-               "03hzd2ikabxhh5ch2yvml2nks2wpv3qbkqmx3520in6khypwgy2l"))))
+               "11qwbid666fspq143ymi86yva2b01lybaqh26k92rciasav3r11j"))))
     (build-system cmake-build-system)
     (arguments
      '(#:configure-flags
@@ -810,14 +810,14 @@ similar to BerkeleyDB, LevelDB, etc.")
 (define-public redis
   (package
     (name "redis")
-    (version "3.0.4")
+    (version "3.0.7")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://download.redis.io/releases/redis-"
                                   version".tar.gz"))
               (sha256
                (base32
-                "1kqjc4qrasadgnl3cg71x3g5qpw2rilyk4pwl151698rb2nr0pm3"))))
+                "08vzfdr67gp3lvk770qpax2c5g2sx8hn6p64jn3jddrvxb2939xj"))))
     (build-system gnu-build-system)
     (arguments
      '(#:tests? #f ; tests related to master/slave and replication fail
diff --git a/gnu/packages/dav.scm b/gnu/packages/dav.scm
index de984faf33..2bbc069472 100644
--- a/gnu/packages/dav.scm
+++ b/gnu/packages/dav.scm
@@ -52,13 +52,16 @@ clients.")
 (define-public vdirsyncer
   (package
     (name "vdirsyncer")
-    (version "0.9.2")
+    (version "0.10.0")
     (source (origin
              (method url-fetch)
-             (uri (pypi-uri "vdirsyncer" version))
+             (uri (string-append "https://pypi.python.org/packages/0b/fb/"
+                                 "c42223e1e9169e4770194e62143d431755724b080d8cb"
+                                 "77f14705b634815/"
+                                 "vdirsyncer-" version ".tar.gz"))
              (sha256
               (base32
-               "1g1107cz4sk41d2z6k6pn9n2fzd26m72j8aj33zn483vfvmyrc4q"))))
+               "1gf86sbd6w0w4zayh9r3irlp5jwrzbjikjc0vs5zkdpa5c199f78"))))
     (build-system python-build-system)
     (arguments
       `(#:phases (modify-phases %standard-phases
@@ -100,7 +103,6 @@ clients.")
        ("python-click" ,python-click)
        ("python-click-log" ,python-click-log)
        ("python-click-threading" ,python-click-threading)
-       ("python-lxml" ,python-lxml)
        ("python-requests-toolbelt" ,python-requests-toolbelt)))
     (synopsis "Synchronize calendars and contacts")
     (description "Vdirsyncer synchronizes your calendars and addressbooks
diff --git a/gnu/packages/dico.scm b/gnu/packages/dico.scm
index 317eeeebea..780d8efcc7 100644
--- a/gnu/packages/dico.scm
+++ b/gnu/packages/dico.scm
@@ -43,9 +43,8 @@
              (sha256
               (base32
                "04pjks075x20d19l623mj50bw64g8i41s63z4kzzqcbg9qg96x64"))
-             (patches (map search-patch
-                           '("cpio-gets-undeclared.patch"
-                             "dico-libtool-deterministic.patch")))))
+             (patches (search-patches "cpio-gets-undeclared.patch"
+                                      "dico-libtool-deterministic.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags (list (string-append "--with-guile-site-dir=" %output
diff --git a/gnu/packages/dillo.scm b/gnu/packages/dillo.scm
new file mode 100644
index 0000000000..0fd84d9177
--- /dev/null
+++ b/gnu/packages/dillo.scm
@@ -0,0 +1,63 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2016 Kei Yamashita <kei@openmailbox.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 Guix 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages dillo)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (guix packages)
+  #:use-module (gnu packages)
+  #:use-module (gnu packages compression)
+  #:use-module (gnu packages fltk)
+  #:use-module (gnu packages fontutils)
+  #:use-module (gnu packages perl)
+  #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages image)
+  #:use-module (gnu packages tls)
+  #:use-module (gnu packages xorg)
+  #:use-module (guix download)
+  #:use-module (guix build-system gnu))
+
+(define-public dillo
+  (package
+    (name "dillo")
+    (version "3.0.5")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://www.dillo.org/download/"
+                                  name "-" version ".tar.bz2"))
+              (sha256
+               (base32
+                "12ql8n1lypv3k5zqgwjxlw1md90ixz3ag6j1gghfnhjq3inf26yv"))))
+    (build-system gnu-build-system)
+    (arguments `(#:configure-flags '("--enable-ssl" "--enable-ipv6")))
+    (native-inputs `(("pkg-config" ,pkg-config)))
+    (inputs `(("fltk" ,fltk)
+              ("fontconfig" ,fontconfig)
+              ("libjpeg" ,libjpeg)
+              ("libpng" ,libpng)
+              ("libxcursor" ,libxcursor)
+              ("libxft" ,libxft)
+              ("libxi" ,libxi)
+              ("libxinerama" ,libxinerama)
+              ("openssl" ,openssl)
+              ("perl" ,perl)
+              ("zlib" ,zlib)))
+    (synopsis "Very small and fast graphical web browser")
+    (description "Dillo is a minimalistic web browser particularly intended for
+older or slower computers and embedded systems.")
+    (home-page "http://www.dillo.org")
+    (license license:gpl3+)))
diff --git a/gnu/packages/docbook.scm b/gnu/packages/docbook.scm
index 9f5fbf1d96..2bd86fe5d2 100644
--- a/gnu/packages/docbook.scm
+++ b/gnu/packages/docbook.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -74,7 +75,7 @@ by no means limited to these applications.)  This package provides XML DTDs.")
 
 (define-public docbook-xml-4.4
   (package (inherit docbook-xml)
-   (version "4.4")
+    (version "4.4")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://www.docbook.org/xml/" version
@@ -85,7 +86,7 @@ by no means limited to these applications.)  This package provides XML DTDs.")
 
 (define-public docbook-xml-4.3
   (package (inherit docbook-xml)
-   (version "4.3")
+    (version "4.3")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://www.docbook.org/xml/" version
@@ -96,7 +97,7 @@ by no means limited to these applications.)  This package provides XML DTDs.")
 
 (define-public docbook-xml-4.2
   (package (inherit docbook-xml)
-   (version "4.2")
+    (version "4.2")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://www.docbook.org/xml/" version
@@ -105,6 +106,29 @@ by no means limited to these applications.)  This package provides XML DTDs.")
                (base32
                 "18hgwvmywh6a5jh38szjmg3hg2r4v5lb6r3ydc3rd8cp9wg61i5c"))))))
 
+(define-public docbook-xml-4.1.2
+  (package (inherit docbook-xml)
+    (version "4.1.2")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://www.docbook.org/xml/" version
+                                  "/docbkx412.zip"))
+              (sha256
+               (base32
+                "0wkp5rvnqj0ghxia0558mnn4c7s3n501j99q2isp3sp0ci069w1h"))))
+    (arguments
+     '(#:modules ((guix build utils))
+       #:builder
+       (begin
+         (use-modules (guix build utils))
+         (let ((source (assoc-ref %build-inputs "source"))
+               (unzip  (string-append (assoc-ref %build-inputs "unzip")
+                                      "/bin/unzip"))
+               (dtd    (string-append (assoc-ref %outputs "out")
+                                      "/xml/dtd/docbook")))
+           (mkdir-p dtd)
+           (zero? (system* unzip source "-d" dtd))))))))
+
 (define-public docbook-xsl
   (package
     (name "docbook-xsl")
diff --git a/gnu/packages/doxygen.scm b/gnu/packages/doxygen.scm
index 8245a65c86..8e4cbb936c 100644
--- a/gnu/packages/doxygen.scm
+++ b/gnu/packages/doxygen.scm
@@ -40,7 +40,7 @@
              (sha256
               (base32
                "0ja02pm3fpfhc5dkry00kq8mn141cqvdqqpmms373ncbwi38pl35"))
-             (patches (list (search-patch "doxygen-test.patch")))))
+             (patches (search-patches "doxygen-test.patch"))))
     (build-system cmake-build-system)
     (native-inputs
      `(("bison" ,bison)
diff --git a/gnu/packages/ebook.scm b/gnu/packages/ebook.scm
index bf7fe70772..f972d8831f 100644
--- a/gnu/packages/ebook.scm
+++ b/gnu/packages/ebook.scm
@@ -50,7 +50,7 @@
              (sha256
                (base32
                 "18zzb4x3z0d7fjh1x5439bs62dmgsi4c1pg3qyr7h5gp1i5xcj9l"))
-             (patches (list (search-patch "chmlib-inttypes.patch")))))
+             (patches (search-patches "chmlib-inttypes.patch"))))
     (build-system gnu-build-system)
     (home-page "http://www.jedrea.com/chmlib/")
     (synopsis "Library for CHM files")
@@ -77,8 +77,8 @@
           '(begin
             (delete-file-recursively "src/unrar")
             (delete-file "src/odf/thumbnail.py")))
-        (patches (list (search-patch "calibre-drop-unrar.patch")
-                       (search-patch "calibre-no-updates-dialog.patch")))))
+        (patches (search-patches "calibre-drop-unrar.patch"
+                                 "calibre-no-updates-dialog.patch"))))
     (build-system python-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
diff --git a/gnu/packages/elf.scm b/gnu/packages/elf.scm
index cb456af195..82604c4e30 100644
--- a/gnu/packages/elf.scm
+++ b/gnu/packages/elf.scm
@@ -39,8 +39,7 @@
               (sha256
                (base32
                 "0w50szymyqvx8g0vkwrvnv17grqxva6x1z9dm9m3i99zg2hr232p"))
-              (patches
-               (list (search-patch "elfutils-tests-ptrace.patch")))))
+              (patches (search-patches "elfutils-tests-ptrace.patch"))))
     (build-system gnu-build-system)
 
     ;; Separate programs because that's usually not what elfutils users want,
@@ -108,7 +107,7 @@ addr2line, and more.")
              (sha256
               (base32
                "1rqpg84wrd3fa16wa9vqdvasnc05yz49w207cz1l0wrl4k8q97y9"))
-             (patches (list (search-patch "patchelf-page-size.patch")))))
+             (patches (search-patches "patchelf-page-size.patch"))))
     (build-system gnu-build-system)
 
     ;; XXX: The upstream 'patchelf' doesn't support ARM.  The only available
diff --git a/gnu/packages/emacs.scm b/gnu/packages/emacs.scm
index db5668e1fc..4ffc3c1b7f 100644
--- a/gnu/packages/emacs.scm
+++ b/gnu/packages/emacs.scm
@@ -6,6 +6,7 @@
 ;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>
 ;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2016 Nils Gillmann <niasterisk@grrlz.net>
+;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -76,8 +77,8 @@
              (sha256
               (base32
                "0kn3rzm91qiswi0cql89kbv6mqn27rwsyjfb8xmwy9m5s8fxfiyx"))
-             (patches (list (search-patch "emacs-exec-path.patch")
-                            (search-patch "emacs-source-date-epoch.patch")))))
+             (patches (search-patches "emacs-exec-path.patch"
+                                      "emacs-source-date-epoch.patch"))))
     (build-system glib-or-gtk-build-system)
     (arguments
      `(#:phases
@@ -300,7 +301,7 @@ when typing parentheses directly or commenting out code line by line.")
 (define-public git-modes
   (package
     (name "git-modes")
-    (version "1.2.1")
+    (version "1.2.2")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -309,7 +310,7 @@ when typing parentheses directly or commenting out code line by line.")
               (file-name (string-append name "-" version ".tar.gz"))
               (sha256
                (base32
-                "088wyddh8y0yw77i0hx449n9zg4wzyc90h63wlmxba1ijg4dzm0p"))))
+                "0gb9c18jib8rpm14vig9774104lwmd8353ps0259m861syf6664d"))))
     (build-system gnu-build-system)
     (arguments
      `(#:modules ((guix build gnu-build-system)
@@ -345,7 +346,7 @@ configuration files, such as .gitattributes, .gitignore, and .git/config.")
 (define-public emacs-with-editor
   (package
     (name "emacs-with-editor")
-    (version "2.5.0")
+    (version "2.5.1")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -354,7 +355,7 @@ configuration files, such as .gitattributes, .gitignore, and .git/config.")
               (file-name (string-append name "-" version ".tar.gz"))
               (sha256
                (base32
-                "19gb381z61l2icg5v5pymgi1a11g3zdp5aysl2j5fh7fxxg4d4c0"))))
+                "1lqm0msc9lzb05ys96bsx8bf2y1qrw27dh5h6qz8lf5i4cbhflw2"))))
     (build-system emacs-build-system)
     (propagated-inputs
      `(("emacs-dash" ,emacs-dash)))
@@ -370,7 +371,7 @@ on stdout instead of using a socket as the Emacsclient does.")
 (define-public magit
   (package
     (name "magit")
-    (version "2.6.0")
+    (version "2.6.2")
     (source (origin
              (method url-fetch)
              (uri (string-append
@@ -378,7 +379,7 @@ on stdout instead of using a socket as the Emacsclient does.")
                    version "/" name "-" version ".tar.gz"))
              (sha256
               (base32
-               "04km5j6118yqz7h3dyfd4ijjd6w3pb76pjlaj25wh1bchf1yilir"))))
+               "0im1jrqw29g5anrrjflj6b2gpyqkvpghnq8zvywxyhmjwzar4rn7"))))
     (build-system gnu-build-system)
     (native-inputs `(("texinfo" ,texinfo)
                      ("emacs" ,emacs-no-x)))
@@ -1300,7 +1301,7 @@ on context.")
           (base32
            "141wn9l0m33w0g3dqmx8nxbfdny1r5xbr6ak61rsz21bk0qafs7x"))
          (patches
-          (list (search-patch "emacs-scheme-complete-scheme-r5rs-info.patch")))))
+          (search-patches "emacs-scheme-complete-scheme-r5rs-info.patch"))))
       (build-system emacs-build-system)
       (home-page "https://github.com/ashinn/scheme-complete")
       (synopsis "Smart tab completion for Scheme in Emacs")
@@ -1377,8 +1378,7 @@ identifiers in the MIT-Scheme documentation.")
        (file-name (string-append name "-" version ".el"))
        (method uncompressed-file-fetch)
        (uri "https://staff.fnwi.uva.nl/c.dominik/Tools/constants/constants.el")
-       (patches
-        (list (search-patch "emacs-constants-lisp-like.patch")))
+       (patches (search-patches "emacs-constants-lisp-like.patch"))
        (sha256
         (base32
          "14q094aphsjhq8gklv7i5a7byl0ygz63cv3n6b5p8ji2jy0mnnw3"))))
@@ -1499,3 +1499,55 @@ without modifier keys.  It's similar to Vim's separation of commands and
 insertion mode.  When enabled all keys are implicitly prefixed with
 @samp{C-} (among other helpful shortcuts).")
       (license license:gpl3+))))
+
+(define-public emacs-rfcview
+  (package
+    (name "emacs-rfcview")
+    (version "0.13")
+    (home-page "http://www.loveshack.ukfsn.org/emacs")
+    (source (origin
+              (method uncompressed-file-fetch)
+              (uri "http://www.loveshack.ukfsn.org/emacs/rfcview.el")
+              (sha256
+               (base32
+                "0ympj5rxig383zl2jf0pzdsa80nnq0dpvjiriq0ivfi98fj7kxbz"))))
+    (build-system emacs-build-system)
+    (native-inputs
+     `(("emacs" ,emacs-no-x)))
+    (synopsis "Prettify Request for Comments (RFC) documents")
+    (description "The Internet Engineering Task Force (IETF) and the Internet
+Society (ISOC) publish various Internet-related protocols and specifications
+as \"Request for Comments\" (RFC) documents and Internet Standard (STD)
+documents.  RFCs and STDs are published in a simple text form.  This package
+provides an Emacs major mode, rfcview-mode, which makes it more pleasant to
+read these documents in Emacs.  It prettifies the text and adds
+hyperlinks/menus for easier navigation.  It also provides functions for
+browsing the index of RFC documents and fetching them from remote servers or
+local directories.")
+    (license license:gpl3+)))
+
+(define-public emacs-ffap-rfc-space
+  (package
+    (name "emacs-ffap-rfc-space")
+    (version "12")
+    (home-page "http://user42.tuxfamily.org/ffap-rfc-space/index.html")
+    (source (origin
+              (method uncompressed-file-fetch)
+              (uri "http://download.tuxfamily.org/user42/ffap-rfc-space.el")
+              (sha256
+               (base32
+                "1iv61dv57a73mdps7rn6zmgz7nqh14v0ninidyrasy45b1nv6gck"))))
+    (build-system emacs-build-system)
+    (native-inputs
+     `(("emacs" ,emacs-no-x)))
+    (synopsis "Make ffap recognize an RFC with a space before its number")
+    (description "The Internet Engineering Task Force (IETF) and the
+Internet Society (ISOC) publish various Internet-related protocols and
+specifications as \"Request for Comments\" (RFC) documents.  The
+built-in Emacs module \"ffap\" (Find File at Point) has the ability to
+recognize names at point which look like \"RFC1234\" and \"RFC-1234\"
+and load the appropriate RFC from a remote server.  However, it fails
+to recognize a name like \"RFC 1234\".  This package enhances ffap so
+that it correctly finds RFCs even when a space appears before the
+number.")
+    (license license:gpl3+)))
diff --git a/gnu/packages/engineering.scm b/gnu/packages/engineering.scm
index 9a36ffbb31..c519ca59e7 100644
--- a/gnu/packages/engineering.scm
+++ b/gnu/packages/engineering.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 David Thompson <davet@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -45,6 +46,7 @@
   #:use-module (gnu packages gtk)
   #:use-module (gnu packages guile)
   #:use-module (gnu packages linux)               ;FIXME: for pcb
+  #:use-module (gnu packages m4)
   #:use-module (gnu packages maths)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages pkg-config)
@@ -124,13 +126,22 @@ plans and designs.")
         'check 'set-home
         (lambda _
           (setenv "HOME" (getenv "TMPDIR")))
-        %standard-phases)))
+        %standard-phases
+        )
+       #:configure-flags
+       (let ((pcb (assoc-ref %build-inputs "pcb")))
+         (list (string-append "--with-pcb-datadir=" pcb "/share")
+               (string-append "--with-pcb-lib-path="
+                              pcb "/share/pcb/pcblib-newlib:"
+                              pcb "/share/pcb/newlib")))))
     (inputs
      `(("glib" ,glib)
        ("gtk" ,gtk+-2)
        ("guile" ,guile-2.0)
        ("desktop-file-utils" ,desktop-file-utils)
-       ("shared-mime-info" ,shared-mime-info)))
+       ("shared-mime-info" ,shared-mime-info)
+       ("m4" ,m4)
+       ("pcb" ,pcb)))
     (native-inputs
      `(("pkg-config" ,pkg-config)
        ("perl" ,perl))) ; for tests
@@ -221,8 +232,8 @@ optimizer; and it can produce photorealistic and design review images.")
               (modules '((guix build utils)
                          (guix build download)
                          (guix ftp-client)))
-              (patches (list (search-patch "fastcap-mulSetup.patch")
-                             (search-patch "fastcap-mulGlobal.patch")))))
+              (patches (search-patches "fastcap-mulSetup.patch"
+                                       "fastcap-mulGlobal.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("texlive" ,texlive)
@@ -318,11 +329,11 @@ multipole-accelerated algorithm.")
                     "-" version ".tar.z"))
               (sha256
                (base32 "1a06xyyd40zhknrkz17xppl2zd5ig4w9g1grc8qrs0zqqcl5hpzi"))
-              (patches (list (search-patch "fasthenry-spAllocate.patch")
-                             (search-patch "fasthenry-spBuild.patch")
-                             (search-patch "fasthenry-spUtils.patch")
-                             (search-patch "fasthenry-spSolve.patch")
-                             (search-patch "fasthenry-spFactor.patch")))))
+              (patches (search-patches "fasthenry-spAllocate.patch"
+                                       "fasthenry-spBuild.patch"
+                                       "fasthenry-spUtils.patch"
+                                       "fasthenry-spSolve.patch"
+                                       "fasthenry-spFactor.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:make-flags '("CC=gcc" "RM=rm" "SHELL=sh" "all")
diff --git a/gnu/packages/firmware.scm b/gnu/packages/firmware.scm
index 271fb49dd7..45b7bf7ab1 100644
--- a/gnu/packages/firmware.scm
+++ b/gnu/packages/firmware.scm
@@ -39,7 +39,7 @@
                (base32
                 "16jbj8avg5jkgvq5lxm0hdxxn4c3zn7fx8b4nxllvr024apk9w23"))
               (file-name (string-append name "-" version "-checkout"))
-              (patches (list (search-patch "ath9k-htc-firmware-objcopy.patch")))))
+              (patches (search-patches "ath9k-htc-firmware-objcopy.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-cons-before
diff --git a/gnu/packages/flashing-tools.scm b/gnu/packages/flashing-tools.scm
index 194ed380bb..9f9f1b9c6a 100644
--- a/gnu/packages/flashing-tools.scm
+++ b/gnu/packages/flashing-tools.scm
@@ -44,7 +44,7 @@
               (sha256
                (base32
                 "1s9pc4yls2s1gcg2ar4q75nym2z5v6lxq36bl6lq26br00nj2mas"))
-              (patches (list (search-patch "flashrom-use-libftdi1.patch")))))
+              (patches (search-patches "flashrom-use-libftdi1.patch"))))
     (build-system gnu-build-system)
     (inputs `(("dmidecode" ,dmidecode)
               ("pciutils" ,pciutils)
@@ -88,7 +88,7 @@ programmer devices.")
       (sha256
        (base32
         "0frxg0q09nrm95z7ymzddx7ysl77ilfbdix1m81d9jjpiv5bm64y"))
-      (patches (list (search-patch "avrdude-fix-libusb.patch")))))
+      (patches (search-patches "avrdude-fix-libusb.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("libelf" ,libelf)
@@ -117,7 +117,7 @@ technique (ISP).")
       (sha256
        (base32
         "15gr99y1z9vbvhrkd25zqhnzhg6zjmaam3vfjzf2mazd39mx7d0x"))
-      (patches (list (search-patch "dfu-programmer-fix-libusb.patch")))))
+      (patches (search-patches "dfu-programmer-fix-libusb.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
diff --git a/gnu/packages/fltk.scm b/gnu/packages/fltk.scm
index 0629d41c0c..bc6b4ab5e6 100644
--- a/gnu/packages/fltk.scm
+++ b/gnu/packages/fltk.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2014 John Darrington <jmd@gnu.org>
 ;;; Copyright © 2015 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2016 Kei Yamashita <kei@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -46,12 +47,14 @@
       (sha256
        (base32
         "15qd7lkz5d5ynz70xhxhigpz3wns39v9xcf7ggkl0792syc8sfgq"))
-      (patches (list (search-patch "fltk-shared-lib-defines.patch")))))
+      (patches (search-patches "fltk-shared-lib-defines.patch"
+                               "fltk-xfont-on-demand.patch"))))
    (build-system gnu-build-system)
    (inputs
     `(("libjpeg" ,libjpeg-8)     ;jpeg_read_header argument error in libjpeg-9
       ("libpng" ,libpng)
       ("libx11" ,libx11)
+      ("libxft" ,libxft)
       ("mesa" ,mesa)
       ("zlib" ,zlib)))
     (arguments
diff --git a/gnu/packages/fonts.scm b/gnu/packages/fonts.scm
index 65d53896e8..deb11841da 100644
--- a/gnu/packages/fonts.scm
+++ b/gnu/packages/fonts.scm
@@ -8,6 +8,7 @@
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2016 Nils Gillmann <niasterisk@grrlz.net>
 ;;; Copyright © 2016 Jookia <166291@gmail.com>
+;;; Copyright © 2016 Eric Bavier <bavier@member.fsf.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -306,7 +307,9 @@ sans-serif designed for on-screen reading.  It is used by GNOME@tie{}3.")
      "The GNU Freefont project aims to provide a set of free outline
  (PostScript Type0, TrueType, OpenType...) fonts covering the ISO
 10646/Unicode UCS (Universal Character Set).")
-   (license license:gpl3+)))
+    (license license:gpl3+)
+    (properties '((upstream-name . "freefont")
+                  (ftp-directory . "/gnu/freefont")))))
 
 (define-public font-liberation
   (package
@@ -759,3 +762,49 @@ It contains the following fonts and styles:
 @item UnGungseo: cursive, brush-stroke.
 @end enumerate\n")
     (license license:gpl2+)))
+
+(define-public font-fantasque-sans
+  (package
+    (name "font-fantasque-sans")
+    (version "1.7.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "https://github.com/belluzj/fantasque-sans/"
+                           "archive/v" version ".tar.gz"))
+       (file-name (string-append name "-" version ".tar.gz"))
+       (sha256
+        (base32
+         "07fpy53k2x2nz5q61swkab6cfk9gw2kc4x4brsj6zjgbm16fap85"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("ttfautohint" ,ttfautohint)
+       ("woff-tools" ,woff-tools)
+       ("fontforge" ,fontforge)
+       ("woff2" ,woff2)
+       ("ttf2eot" ,ttf2eot)))
+    (arguments
+     `(#:tests? #f                 ;test target intended for visual inspection
+       #:phases (modify-phases %standard-phases
+                  (delete 'configure)   ;no configuration
+                  (replace 'install
+                    ;; 'make install' wants to install to ~/.fonts, install to
+                    ;; output instead.
+                    (lambda* (#:key outputs #:allow-other-keys)
+                      (let* ((out (assoc-ref outputs "out"))
+                             (font-dir (string-append out "/share/fonts"))
+                             (truetype-dir (string-append font-dir "/truetype"))
+                             (opentype-dir (string-append font-dir "/opentype"))
+                             (webfonts-dir (string-append font-dir "/webfonts")))
+                        (copy-recursively "OTF" opentype-dir)
+                        (for-each (lambda (f) (install-file f truetype-dir))
+                                  (find-files "." "\\.ttf$"))
+                        (copy-recursively "Webfonts" webfonts-dir)
+                        #t))))))
+    (synopsis "Font family with a monospaced variant for programmers")
+    (description
+     "Fantasque Sans Mono is a programming font designed with functionality in
+mind.  The font includes a bold version and a good italic version with new
+glyph designs, not just an added slant.")
+    (home-page "https://fontlibrary.org/en/font/fantasque-sans-mono")
+    (license license:silofl1.1)))
diff --git a/gnu/packages/fontutils.scm b/gnu/packages/fontutils.scm
index 8d33211fb6..0ce7e6039d 100644
--- a/gnu/packages/fontutils.scm
+++ b/gnu/packages/fontutils.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015 Andreas Enge <andreas@enge.fr>
-;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2014, 2016 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2016 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
@@ -29,6 +29,8 @@
   #:use-module (gnu packages gettext)
   #:use-module (gnu packages python)
   #:use-module (gnu packages image)
+  #:use-module (gnu packages bison)
+  #:use-module (gnu packages flex)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages gtk)
@@ -37,6 +39,7 @@
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix svn-download)
+  #:use-module (guix git-download)
   #:use-module (guix build-system cmake)
   #:use-module (guix build-system gnu))
 
@@ -70,6 +73,155 @@ anti-aliased glyph bitmap generation with 256 gray levels.")
    (license license:freetype)           ; some files have other licenses
    (home-page "http://www.freetype.org/")))
 
+(define-public ttfautohint
+  (package
+    (name "ttfautohint")
+    (version "1.5")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "mirror://savannah/freetype/ttfautohint-"
+                           version ".tar.gz"))
+       (sha256
+        (base32
+         "1lgghck46p33z3hg8dnl76jryig4fh6d8rhzms837zp7x4hyfkv4"))
+       (patches (list (search-patch "ttfautohint-source-date-epoch.patch")))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("flex" ,flex)
+       ("bison" ,bison)
+       ("pkg-config" ,pkg-config)))
+    (inputs
+     `(("freetype" ,freetype)
+       ("harfbuzz" ,harfbuzz)))
+    (arguments
+     `(#:configure-flags '("--with-qt=no"))) ;no gui
+    (synopsis "Automated font hinting")
+    (description
+     "ttfautohint provides a 99% automated hinting process and a platform for
+finely hand-hinting the last 1%.  It is ideal for web fonts and supports many
+scripts.")
+    (license (list license:gpl2+ license:freetype)) ;choose one or the other
+    (home-page "http://www.freetype.org/ttfautohint/")))
+
+(define-public woff-tools
+  (package
+    (name "woff-tools")
+    (version "2009.10.04")
+    (source
+     (origin
+       (method url-fetch)
+       ;; Upstream source is unversioned, so use Debian's versioned tarball
+       (uri (string-append "mirror://debian/pool/main/w/woff-tools/"
+                           "woff-tools_" version ".orig.tar.gz"))
+       (file-name (string-append name "-" version ".tar.gz"))
+       (sha256
+        (base32
+         "1i97gkqa6jfzlslsngqf556kx60knlgf7yc9pzsq2pizc6f0d4zl"))))
+    (build-system gnu-build-system)
+    (inputs
+     `(("zlib" ,zlib)))
+    (arguments
+     `(#:make-flags '("CC=gcc")
+       #:tests? #f                      ;no tests
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)            ;no configuration
+         (replace 'install
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin")))
+               (install-file "sfnt2woff" bin)
+               (install-file "woff2sfnt" bin)))))))
+    (synopsis "Convert between OpenType and WOFF fonts")
+    (description
+     "This package provides two tools:
+@table @code
+@item sfnt2woff
+Converts OpenType fonts to WOFF fonts
+@item woff2sfnt
+Converts WOFF fonts to OpenType fonts
+@end table")
+    (license (list license:mpl1.1 license:gpl2+ license:lgpl2.1+))
+    (home-page "https://people.mozilla.com/~jkew/woff/")))
+
+(define-public ttf2eot
+  (package
+    (name "ttf2eot")
+    (version "0.0.2-2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "https://storage.googleapis.com/"
+                           "google-code-archive-downloads/v2/"
+                           "code.google.com/ttf2eot/"
+                           "ttf2eot-" version ".tar.gz"))
+       (sha256
+        (base32
+         "1f4dzzmhn0208dvbm3ia5ar6ls9apwc6ampy5blmfxkigi6z0g02"))
+       (patches (list (search-patch "ttf2eot-cstddef.patch")))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f                      ;no tests
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)            ;no configuration
+         (replace 'install
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin")))
+               (install-file "ttf2eot" bin)))))))
+    (synopsis "Convert from TrueType to Embeddable Open Type")
+    (description
+     "This package contains a commandline wrapper around OpenTypeUtilities.cpp
+from Chromium, used to make EOT (Embeddable Open Type) files from
+TTF (TrueType/OpenType Font) files.")
+    ;; While the README states "License: Derived from WebKit, so BSD/LGPL
+    ;; 2/LGPL 2.1", the single derived source file includes only BSD in its
+    ;; license header, and the wrapper source contains no license header.
+    (license license:bsd-2)
+    (home-page "https://code.google.com/archive/p/ttf2eot/")))
+
+(define-public woff2
+  (let ((commit "4e698b8c6c5e070d53c340db9ddf160e21070ede")
+        (revision "1"))
+    (package
+      (name "woff2")
+      (version (string-append "20160306-" revision "."
+                              (string-take commit 7)))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url "https://github.com/google/woff2.git")
+                      (commit commit)))
+                (file-name (string-append name "-" version ".tar.xz"))
+                (sha256
+                 (base32
+                  "0wka0yhf0cjmd4rv2jckxpyv6lb5ckj4nj0k1ajq5hrjy7f30lcp"))
+                (patches (list (search-patch "woff2-libbrotli.patch")))))
+      (build-system gnu-build-system)
+      (native-inputs
+       `(("pkg-config" ,pkg-config)))
+      (inputs
+       `(("brotli" ,brotli)))
+      (arguments
+       `(#:tests? #f                    ;no tests
+         #:phases (modify-phases %standard-phases
+                    (delete 'configure)
+                    (replace 'install
+                      (lambda* (#:key outputs #:allow-other-keys)
+                        (let* ((out (assoc-ref outputs "out"))
+                               (bin (string-append out "/bin")))
+                          (install-file "woff2_compress" bin)
+                          (install-file "woff2_decompress" bin)
+                          #t))))))
+      (synopsis "Compress TrueType fonts to WOFF2")
+      (description
+       "This package provides utilities for compressing/decompressing TrueType
+fonts to/from the WOFF2 format.")
+      (license license:asl2.0)
+      (home-page "https://github.com/google/woff2"))))
+
 (define-public fontconfig
   (package
    (name "fontconfig")
@@ -341,30 +493,26 @@ definitions.")
 (define-public fontforge
   (package
    (name "fontforge")
-   (version "20150824")
+   (version "20160404")
    (source (origin
             (method url-fetch)
             (uri (string-append
                   "https://github.com/fontforge/fontforge/releases/download/"
-                  version "/fontforge-" version ".tar.gz"))
+                  version "/fontforge-dist-" version ".tar.gz"))
             (sha256 (base32
-                     "0gfcm8yn1d30giqhdwbchnfnspcqypqdzrxlhqhwy1i18wgl0v2v"))
+                     "1kavnhbkzc1hk6f39fynq9s0haama81ddrbld4b5x60d0dbaawvc"))
             (modules '((guix build utils)))
             (snippet
              '(begin
                ;; Make builds bit-reproducible by using fixed date strings.
                (substitute* "configure"
                  (("^FONTFORGE_MODTIME=.*$")
-                  "FONTFORGE_MODTIME=\"1458399002\"\n")
+                  "FONTFORGE_MODTIME=\"1459819518L\"\n")
                  (("^FONTFORGE_MODTIME_STR=.*$")
-                  "FONTFORGE_MODTIME_STR=\"15:50 CET 19-Mar-2016\"\n")
+                  "FONTFORGE_MODTIME_STR=\"20:25 CDT  4-Apr-2016\"\n")
                  (("^FONTFORGE_VERSIONDATE=.*$")
-                  "FONTFORGE_VERSIONDATE=\"20160319\"\n"))
-
-               ;; Make TTF builds bit-reproducible by clearing the timestamp
-               ;; that goes in TTF files.
-               (substitute* "fontforge/tottf.c"
-                 (("cvt_unix_to_1904\\(now") "cvt_unix_to_1904(0"))))))
+                  "FONTFORGE_VERSIONDATE=\"20160404\"\n"))))
+            (patches (list (search-patch "fontforge-svg-modtime.patch")))))
    (build-system gnu-build-system)
    (native-inputs
     `(("pkg-config" ,pkg-config)))
@@ -372,7 +520,6 @@ definitions.")
              ("fontconfig"      ,fontconfig) ;dlopen'd
              ("freetype"        ,freetype)
              ("gettext"         ,gnu-gettext)
-             ("giflib"          ,giflib) ;needs giflib 4.*
              ("glib"            ,glib) ;needed for pango detection
              ("libICE"          ,libice)
              ("libSM"           ,libsm)
@@ -383,6 +530,7 @@ definitions.")
              ("libpng"          ,libpng)
              ("libspiro"        ,libspiro)
              ("libtiff"         ,libtiff)
+             ("libungif"        ,libungif)
              ("libuninameslist" ,libuninameslist)
              ("libxft"          ,libxft)
              ("libxml2"         ,libxml2)
@@ -393,39 +541,30 @@ definitions.")
    (arguments
     '(#:tests? #f
       #:phases
-      (alist-cons-before
-       'configure 'patch-configure
-       (lambda* (#:key inputs #:allow-other-keys)
-         (let ((libxml2 (assoc-ref inputs "libxml2"))
-               (cairo   (assoc-ref inputs "cairo"))
-               (pango   (assoc-ref inputs "pango")))
-           (substitute* "configure"
-             ;; configure looks for a directory to be present to determine
-             ;; whether libxml2 is available, rather than checking for the
-             ;; library or headers.  Point it to the correct directory.
-             (("/usr/include/libxml2")
-              (string-append libxml2 "/include/libxml2"))
-             ;; Similary, the search directories for cairo and pango are
-             ;; hard-coded.
-             (("gww_prefix in.*") (string-append "gww_prefix in "
-                                                 cairo " " pango "\n")))))
-       (alist-cons-after
-        'install 'set-library-path
-        (lambda* (#:key inputs outputs #:allow-other-keys)
-          (let ((out (assoc-ref outputs "out"))
-                (potrace (string-append (assoc-ref inputs "potrace") "/bin")))
-            (wrap-program (string-append out "/bin/fontforge")
-                          ;; Fontforge dynamically opens libraries.
-                          `("LD_LIBRARY_PATH" ":" prefix
-                            ,(map (lambda (input)
-                                    (string-append (assoc-ref inputs input)
-                                                   "/lib"))
-                                  '("libtiff" "libjpeg" "libpng" "giflib"
-                                    "libxml2" "zlib" "libspiro" "freetype"
-                                    "pango" "cairo" "fontconfig")))
-                          ;; Checks for potrace program at runtime
-                          `("PATH" ":" prefix (,potrace)))))
-        %standard-phases))))
+      (modify-phases %standard-phases
+        (add-after 'build 'build-contrib
+          (lambda* (#:key outputs #:allow-other-keys)
+            (let* ((out (assoc-ref outputs "out"))
+                   (bin (string-append out "/bin")))
+              (and (zero? (system* "make" "-Ccontrib/fonttools"
+                                   "CC=gcc" "showttf"))
+                   (begin (install-file "contrib/fonttools/showttf" bin)
+                          #t)))))
+        (add-after 'install 'set-library-path
+          (lambda* (#:key inputs outputs #:allow-other-keys)
+            (let ((out (assoc-ref outputs "out"))
+                  (potrace (string-append (assoc-ref inputs "potrace") "/bin")))
+              (wrap-program (string-append out "/bin/fontforge")
+                ;; Fontforge dynamically opens libraries.
+                `("LD_LIBRARY_PATH" ":" prefix
+                  ,(map (lambda (input)
+                          (string-append (assoc-ref inputs input)
+                                         "/lib"))
+                        '("libtiff" "libjpeg" "libpng" "libungif"
+                          "libxml2" "zlib" "libspiro" "freetype"
+                          "pango" "cairo" "fontconfig")))
+                ;; Checks for potrace program at runtime
+                `("PATH" ":" prefix (,potrace)))))))))
    (synopsis "Outline font editor")
    (description
     "FontForge allows you to create and modify postscript, truetype and
diff --git a/gnu/packages/ftp.scm b/gnu/packages/ftp.scm
index acd69adcd0..4c2d893c17 100644
--- a/gnu/packages/ftp.scm
+++ b/gnu/packages/ftp.scm
@@ -43,9 +43,8 @@
               (sha256
                (base32
                 "1grmp8zg7cjgjinz66mrh53whigkqzl90nlxj05hapnhk3ns3vni"))
-              (patches
-               (list (search-patch
-                      "lftp-dont-save-unknown-host-fingerprint.patch")))))
+              (patches (search-patches
+                        "lftp-dont-save-unknown-host-fingerprint.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
@@ -126,7 +125,7 @@ FTP browser, as well as non-interactive commands such as 'ncftpput' and
         (sha256
           (base32
             "0f5cj5p852wkm24mzy2sxgxyahv2p9rk4wlq21j310pi7wlhgwyl"))
-        (patches (list (search-patch "weex-vacopy.patch")))))
+        (patches (search-patches "weex-vacopy.patch"))))
     (build-system gnu-build-system)
     (arguments
       `(#:phases
diff --git a/gnu/packages/game-development.scm b/gnu/packages/game-development.scm
index 0a58a7efa5..414af14f28 100644
--- a/gnu/packages/game-development.scm
+++ b/gnu/packages/game-development.scm
@@ -6,6 +6,7 @@
 ;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
 ;;; Copyright © 2015, 2016 David Thompson <davet@gnu.org>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Kei Yamashita <kei@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -407,3 +408,35 @@ games.  In addition to basic pixel editing features, Aseprite can assist in
 the creation of animations, tiled graphics, texture atlases, and more.")
     (home-page "http://www.aseprite.org/")
     (license license:gpl2+)))
+
+(define-public qqwing
+  (package
+    (name "qqwing")
+    (version "1.3.4")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://qqwing.com/"
+                    name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0bw0papyqjg22z6irf36gs54y8236wa37b6gyn2h1spy65n76lqp"))))
+    (build-system gnu-build-system)
+    (native-inputs
+      `(("pkg-config" ,pkg-config)))
+    (home-page "https://qqwing.com/")
+    (synopsis "Sudoku puzzle solver and generator")
+    (description
+     "QQWing is a Sudoku puzzle generator and solver.
+It offers the following features:
+@enumerate
+@item Can solve 1000 puzzles in 1 second and generate 1000 puzzles in 25 seconds.
+@item Uses logic.  Uses as many solve techniques as possible when solving
+  puzzles rather than guessing.
+@item Rates puzzles.  Most generators don't give an indication of the difficulty
+  of a Sudoku puzzle.  QQwing does.
+@item Can print solve instructions for any puzzle.
+@item Customizable output style, including a CSV style that is easy to
+  import into a database.
+@end enumerate")
+    (license license:gpl2+)))
diff --git a/gnu/packages/games.scm b/gnu/packages/games.scm
index 653e0c7206..34998cea28 100644
--- a/gnu/packages/games.scm
+++ b/gnu/packages/games.scm
@@ -17,6 +17,8 @@
 ;;; Copyright © 2016 Rodger Fox <thylakoid@openmailbox.org>
 ;;; Copyright © 2016 Manolis Fragkiskos Ragkousis <manolis837@gmail.com>
 ;;; Copyright © 2016 Nils Gillmann <niasterisk@grrlz.net>
+;;; Copyright © 2016 Albin Söderqvist <albin@fripost.org>
+;;; Copyright © 2016 Kei Yamashita <kei@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -34,6 +36,7 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu packages games)
+  #:use-module (ice-9 match)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix utils)
   #:use-module (guix packages)
@@ -61,6 +64,7 @@
   #:use-module (gnu packages libunwind)
   #:use-module (gnu packages haskell)
   #:use-module (gnu packages mp3)
+  #:use-module (gnu packages icu4c)
   #:use-module (gnu packages image)
   #:use-module (gnu packages ncurses)
   #:use-module (gnu packages python)
@@ -220,7 +224,7 @@ that beneath its ruins lay buried an ancient evil.")
        (sha256
         (base32
          "0q34d2k6anzqvb0mf67x85q92lfx9jr71ry13dlp47jx0x9i573m"))
-       (patches (list (search-patch "pingus-sdl-libs-config.patch")))))
+       (patches (search-patches "pingus-sdl-libs-config.patch"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)
                      ("scons" ,scons)))
@@ -598,8 +602,8 @@ for common mesh file formats, and collision detection.")
                 (sha256
                  (base32
                   "1r4c5gap1z2zsv4yjd34qriqkxaq4lb4rykapyzkkdf4g36lc3nh"))
-                (patches (list (search-patch "mars-sfml-2.3.patch")
-                               (search-patch "mars-install.patch")))))
+                (patches (search-patches "mars-sfml-2.3.patch"
+                                         "mars-install.patch"))))
       (build-system cmake-build-system)
       (arguments
        `(#:tests? #f        ; There are no tests
@@ -1185,7 +1189,7 @@ is programmed in Haskell.")
 (define-public manaplus
   (package
     (name "manaplus")
-    (version "1.6.3.12")
+    (version "1.6.4.23")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -1193,7 +1197,7 @@ is programmed in Haskell.")
                     version "/manaplus-" version ".tar.xz"))
               (sha256
                (base32
-                "02bnd4nk1qzrfqckqkwb6sbjzsmacv968ih74cdgcykslpsr684d"))))
+                "1ja2w86rz3pliq0sdc7yxppsdjg3d1ymcx9fdsiwnw6fv5a8nbzj"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags
@@ -1709,8 +1713,7 @@ Z64 video plugin.")
        (file-name (string-append name "-" version ".tar.gz"))
        (sha256
         (base32 "04qkpd8ic7xsgnqz7spl00wxdygf79m7d1k8rabbygjk5lg6p8z2"))
-       (patches
-        (list (search-patch "mupen64plus-ui-console-notice.patch")))))
+       (patches (search-patches "mupen64plus-ui-console-notice.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
@@ -1859,6 +1862,74 @@ and a game metadata scraper.")
     (home-page "http://www.emulationstation.org")
     (license license:expat)))
 
+(define openttd-engine
+  (package
+    (name "openttd-engine")
+    (version "1.6.0")
+    (source
+     (origin (method url-fetch)
+             (uri (string-append "http://binaries.openttd.org/releases/"
+                                 version "/openttd-" version "-source.tar.xz"))
+             (sha256
+              (base32
+               "1cjf9gz7d0sn7893wv9d00q724sxv3d81bgb0c5f5ppz2ssyc4jc"))
+             (modules '((guix build utils)))
+             (snippet
+              ;; The DOS port contains proprietary software.
+              '(delete-file-recursively "os/dos"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f              ; no "check" target
+       #:phases
+       (modify-phases %standard-phases
+         ;; The build process fails if the configure script is passed the
+         ;; option "--enable-fast-install".
+         (replace 'configure
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out"))
+                   (lzo (assoc-ref inputs "lzo")))
+               (zero?
+                (system* "./configure"
+                         (string-append "--prefix=" out)
+                         ;; Provide the "lzo" path.
+                         (string-append "--with-liblzo2="
+                                        lzo "/lib/liblzo2.a")
+                         ;; Put the binary in 'bin' instead of 'games'.
+                         "--binary-dir=bin"))))))))
+    (native-inputs `(("pkg-config" ,pkg-config)))
+    (inputs
+     `(("allegro" ,allegro-4)
+       ("fontconfig" ,fontconfig)
+       ("freetype" ,freetype)
+       ("icu4c" ,icu4c)
+       ("libpng" ,libpng)
+       ("lzo" ,lzo)
+       ("sdl" ,sdl)
+       ("xz" ,xz)
+       ("zlib" ,zlib)))
+    (synopsis "Transportation economics simulator")
+    (description "OpenTTD is a game in which you transport goods and
+passengers by land, water and air.  It is a re-implementation of Transport
+Tycoon Deluxe with many enhancements including multiplayer mode,
+internationalization support, conditional orders and the ability to clone,
+autoreplace and autoupdate vehicles.")
+    (home-page "http://openttd.org/")
+    ;; This package is GPLv2, except for a few files located in
+    ;; "src/3rdparty/" which are under the 3-clause BSD, LGPLv2.1+ and Zlib
+    ;; licenses.  In addition, this software contains an in-game downloader
+    ;; from which the user may find non-functional data licensed under
+    ;; different terms.
+    (license (list license:bsd-3 license:gpl2 license:lgpl2.1+ license:zlib))))
+
+;; TODO Add 'openttd-opengfx' and 'openttd-openmsx' packages and make
+;; 'openttd' a wrapper around them.  The engine is playable by itself,
+;; but it asks a user to download graphics if it's not found.
+
+(define-public openttd
+  (package
+    (inherit openttd-engine)
+    (name "openttd")))
+
 (define-public pinball
   (package
     (name "pinball")
@@ -1871,12 +1942,11 @@ and a game metadata scraper.")
              (sha256
               (base32
                "1f2whlrfidwfh8lvr8cspcyirc6840r5d1ajm7x99qmngygrhixs"))
-             (patches (map search-patch
-                           '("pinball-const-fix.patch"
-                             "pinball-cstddef.patch"
-                             "pinball-missing-separators.patch"
-                             "pinball-src-deps.patch"
-                             "pinball-system-ltdl.patch")))))
+             (patches (search-patches "pinball-const-fix.patch"
+                                      "pinball-cstddef.patch"
+                                      "pinball-missing-separators.patch"
+                                      "pinball-src-deps.patch"
+                                      "pinball-system-ltdl.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("glu" ,glu)
@@ -1965,7 +2035,7 @@ players.")
               (sha256
                (base32
                 "1hxrlv6n8py48j487i6wbb4n4vd55w0na69r7ccmmr9vmrsw5mlk"))
-              (patches (list (search-patch "einstein-build.patch")))))
+              (patches (search-patches "einstein-build.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("freetype" ,freetype)
@@ -2026,3 +2096,148 @@ is attributed to Albert Einstein.")
 the chat server psyced with the specific config located at
 http://lavachat.symlynx.com/unix/")
     (license license:gpl2+)))
+
+(define-public redeclipse
+  (let ((data-sources
+         '(("acerspyro"   "0gxxr6nbac918b49x1cp72nw951hqm5m4iyi2shb1612ly384w8q")
+           ("actors"      "1jq9q82m6nx07nwpb5cnpdcwa33jrcgg0j2yir8zk6zpnxdmp0il")
+           ("appleflap"   "1cn41c6xs68l88rmphqh4rlsh6h04xnkkvklxdpqpvvr4zlsmi85")
+           ("blendbrush"  "0wjbgnniirl9arv274m8mpdqbbq7d09g0pq1z9dl56sazmbk5yy0")
+           ("caustics"    "0gxv1pqhi6c27mqi9mwqyfnzv9rq5sva1vgxhb9ljh231rmkdc15")
+           ("crosshairs"  "0vlyhd10mly2qnjpwvss9ani7dg3v2njpf7457ilx7fk9a3hlbkk")
+           ("elyvisions"  "0s0l77rd9fd09imvj05pwcz4bqrn3j8qsw8prv5pi5bqa50mbn19")
+           ("fonts"       "0apn8j9lf43nmnidq1f0azhrr1n896g7si4djbix1bwll6ild0mq")
+           ("freezurbern" "0y60s3g8v8bl2m6pk2yr9fzl67ymv821x6l2f9hszzydlcjwlscn")
+           ("john"        "1lmwn0r7qpyac2qrnkv9llhsbyzqpgr27hxq2qn1rfbq12fja0ld")
+           ("jojo"        "0sh3ricqlqw868a0mz2n9iw7lhp650pysd2wkcdizhcmw2hlayx9")
+           ("jwin"        "1r459jhxx64j3vdw886ypkm6zg0yg6cr2qark54i1zdskjhp762k")
+           ("luckystrike" "08xq87crcz0jq45q1g6p8h4xrm1bcqzd019zp7n0f9c3p9j6al91")
+           ("maps"        "1f0hqh8mbd4nzqi4hja4k5f380nszhx8igajg5ini4p9cp39x9vi")
+           ("mayhem"      "1hn9jp64aiz8k6p2nxyg82h2nc8fadgghzhrm26y7i4bz9xwxacm")
+           ("mikeplus64"  "1kj2zznxykgm3f1h1fvd8xzim5f292lyh96l2gj5km1nynzjmaap")
+           ("misc"        "1phmzjs5rmika3568b7jb6ywbsi40r711rhg8cbsflllcp7hdidf")
+           ("nobiax"      "08in9c24m2pq7x371q10ny4q3l1l3zb8m029iypy2lx9gr99i7hm")
+           ("particles"   "0wcd3s6vhrjknffnfqrcpkcqk1r01f1fiz6q7n4srhpdv3i4d6vm")
+           ("philipk"     "1s0kmap8iv5sddanrhycblskj3ywvz9xg2m11f6vnfy108palkga")
+           ("projectiles" "0xdhrs9rsncd1f88s5igdbfksli7h0irg5jdbj6p2a3rgdzb3gnj")
+           ("props"       "1sbh3a94pmzic78bil0dvdh4fd8s6gh52f77jdram3w0gwv79x3r")
+           ("skyboxes"    "0hy95a6ps0fk4cq8j6pjipk8rnsjna9bm0ly2l373gbshlfg6zgi")
+           ("sounds"      "1pnyd7acm19sj1k1cy9hq3n3dnzzaiak7j5f0h7fikiybq5rdk7b")
+           ("textures"    "0gxfnc4xm0kp3pd7lhd4yy1dqq00g727h21l64nyiw2b2d6n1755")
+           ("torley"      "1cri5mf8ls8mvpn1x1p9hacyg9ibilaiz07gqv2hl2q8ww5xc1s6")
+           ("trak"        "0xyk5z59kn9ym9n5fdcrwhqig6gjcjgnrgi9rqbbai713w9vpsbq")
+           ("ulukai"      "0ziv9c4inmza40mas1w9dp048y6f646x00bs7kqv33hd1snbg3v3")
+           ("unnamed"     "0hm291k9azilnp0m04zhm52vml1rhxk1z4l74v66spbikr6s2zdx")
+           ("vanities"    "1qbc2v67kdrlvq10miw3dfmg3j9w9bq1hgqrzjcbph0l4gra1ndw")
+           ("vegetation"  "13928yw0wflcj620cmp8rqwplaw8508f3j4zi32vxida1ksz6xn0")
+           ("weapons"     "1ghn6nfcnd5lyl8dnj22csldvf9hrb32wjzpab4sjjz3iyv0zmr3")
+           ("wicked"      "0q9badvg6ix5rhl05s83kw2v6a49jpnbkqk4ls89qahaddfagi8g"))))
+    (package
+      (name "redeclipse")
+      (version "1.5.3")
+      (source (origin
+                (method url-fetch)
+                (uri (string-append "https://github.com/red-eclipse/base"
+                                    "/archive/v" version ".tar.gz"))
+                (file-name (string-append name "-" version ".tar.gz"))
+                (sha256
+                 (base32
+                  "1y0jv5lz69zisiw8sd5z9a9v21zc83by1sx9b7dly78ngif4gc4l"))))
+      (build-system gnu-build-system)
+      (arguments
+       `(#:tests? #f            ; no check target
+         #:make-flags (list "CC=gcc" "-Csrc"
+                            (string-append "INSTDIR="
+                                           (assoc-ref %outputs "out") "/bin"))
+         #:phases
+         (modify-phases %standard-phases
+           (add-after 'unpack 'unpack-data
+             (lambda* (#:key inputs #:allow-other-keys)
+               (delete-file-recursively "data")
+               (mkdir "data")
+               (for-each (lambda (name)
+                           (system* "tar" "-xvf"
+                                    (assoc-ref inputs name)
+                                    "-Cdata"
+                                    "--transform"
+                                    (string-append "s/"
+                                                   name "-1.5.3/"
+                                                   name "/")))
+                         (list ,@(map car data-sources)))
+               #t))
+           (delete 'configure)  ; no configure script
+           (add-after 'set-paths 'set-sdl-paths
+             (lambda* (#:key inputs #:allow-other-keys)
+               (setenv "CPATH"
+                       (string-append (assoc-ref inputs "sdl-union")
+                                      "/include/SDL"))
+               #t))
+           (add-after 'install 'copy-data
+             (lambda* (#:key outputs #:allow-other-keys)
+               (let ((out (assoc-ref outputs "out")))
+                 (copy-recursively "config"
+                                   (string-append out "/config"))
+                 (copy-recursively "data"
+                                   (string-append out "/data")))
+               #t))
+           (add-after 'copy-data 'wrap-program
+             (lambda* (#:key inputs outputs #:allow-other-keys)
+               (let* ((out (assoc-ref outputs "out"))
+                      (bin (string-append out "/bin")))
+                 (with-directory-excursion bin
+                   (rename-file "redeclipse_linux"
+                                ".redeclipse_linux-real")
+                   (rename-file "redeclipse_server_linux"
+                                ".redeclipse_server_linux-real")
+                   (call-with-output-file "redeclipse_linux"
+                     (lambda (port)
+                       (format port "#!~a/bin/sh
+# Run the thing from its home, otherwise it just bails out.
+cd \"~a\"
+exec -a \"$0\" ~a/.redeclipse_linux-real~%"
+                               (assoc-ref inputs "bash") ;implicit input
+                               (string-append out)
+                               (string-append bin))))
+                   (call-with-output-file "redeclipse_server_linux"
+                     (lambda (port)
+                       (format port "#!~a/bin/sh
+# Run the thing from its home, otherwise it just bails out.
+cd \"~a\"
+exec -a \"$0\" ~a/.redeclipse_server_linux-real~%"
+                               (assoc-ref inputs "bash") ;implicit input
+                               (string-append out)
+                               (string-append bin))))
+                   (chmod "redeclipse_linux" #o555)
+                   (chmod "redeclipse_server_linux" #o555)))
+               #t)))))
+      (native-inputs `(("pkg-config" ,pkg-config)))
+      (inputs
+       `(("curl" ,curl)
+         ("glu" ,glu)
+         ("sdl-union" ,(sdl-union))
+         ;; Create origin records for the many separate data packages.
+         ,@(map (match-lambda
+                  ((name hash)
+                   (list name
+                         (origin
+                           (method url-fetch)
+                           (uri (string-append
+                                 "https://github.com/red-eclipse/"
+                                 name "/archive/v" version ".tar.gz"))
+                           (sha256 (base32 hash))
+                           (file-name (string-append name "-" version
+                                                     ".tar.gz"))))))
+                data-sources)))
+      (home-page "http://redeclipse.net/")
+      (synopsis "Arena shooter derived from the Cube 2 engine")
+      (description
+       "Red Eclipse is an arena shooter, created from the Cube2 engine.
+Offering an innovative parkour system and distinct but all potent weapons,
+Red Eclipse provides fast paced and accessible gameplay.")
+      ;; The engine is under Zlib; data files are covered by the other
+      ;; licenses.  More details at <http://redeclipse.net/wiki/License>.
+      (license (list license:expat
+                     license:zlib
+                     license:cc-by-sa3.0
+                     license:cc-by3.0
+                     license:cc0)))))
diff --git a/gnu/packages/gawk.scm b/gnu/packages/gawk.scm
index 8f2805cd4b..c6d322b708 100644
--- a/gnu/packages/gawk.scm
+++ b/gnu/packages/gawk.scm
@@ -36,7 +36,7 @@
                                 ".tar.xz"))
             (sha256
              (base32 "09d6pmx6h3i2glafm0jd1v1iyrs03vcyv2rkz12jisii3vlmbkz3"))
-            (patches (list (search-patch "gawk-fts-test.patch")))))
+            (patches (search-patches "gawk-fts-test.patch"))))
    (build-system gnu-build-system)
    (arguments
     `(#:parallel-tests? #f                ; test suite fails in parallel
diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm
index 8b3c891c52..04d3f93369 100644
--- a/gnu/packages/gcc.scm
+++ b/gnu/packages/gcc.scm
@@ -328,7 +328,7 @@ Go.  It also includes runtime support libraries for these languages.")
               (sha256
                (base32
                 "08yggr18v373a1ihj0rg2vd6psnic42b518xcgp3r9k81xz1xyr2"))
-              (patches (list (search-patch "gcc-arm-link-spec-fix.patch")))))))
+              (patches (search-patches "gcc-arm-link-spec-fix.patch"))))))
 
 (define-public gcc-4.9
   (package (inherit gcc-4.8)
@@ -340,7 +340,7 @@ Go.  It also includes runtime support libraries for these languages.")
               (sha256
                (base32
                 "0zmnm00d2a1hsd41g34bhvxzvxisa2l584q3p447bd91lfjv4ci3"))
-              (patches (list (search-patch "gcc-libvtv-runpath.patch")))))))
+              (patches (search-patches "gcc-libvtv-runpath.patch"))))))
 
 (define-public gcc-5
   (package (inherit gcc-4.9)
@@ -352,10 +352,8 @@ Go.  It also includes runtime support libraries for these languages.")
               (sha256
                (base32
                 "1ny4smkp5bzs3cp8ss7pl6lk8yss0d9m4av1mvdp72r1x695akxq"))
-              (patches (list (search-patch "gcc-5.0-libvtv-runpath.patch")
-                             (search-patch
-                              "gcc-libiberty-printf-decl.patch")))))
-
+              (patches (search-patches "gcc-5.0-libvtv-runpath.patch"
+                                       "gcc-libiberty-printf-decl.patch"))))
     ;; GCC 5 ships with .info files, so no need for Texinfo.
     (native-inputs '())))
 
diff --git a/gnu/packages/gd.scm b/gnu/packages/gd.scm
index 55caac9b29..6ae5579b9c 100644
--- a/gnu/packages/gd.scm
+++ b/gnu/packages/gd.scm
@@ -83,9 +83,8 @@ most common applications of GD involve website development.")
        (sha256
         (base32
          "1ya8f9hpiax8j29vwaiwlvvgah0vkyvpzva28r8231nyk0f3s40z"))
-       (patches
-        (list
-         (search-patch "perl-gd-options-passthrough-and-fontconfig.patch")))))
+       (patches (search-patches
+                 "perl-gd-options-passthrough-and-fontconfig.patch"))))
     (build-system perl-build-system)
     (native-inputs
      `(("perl-module-build" ,perl-module-build))) ;needs Module::Build >= 0.42
diff --git a/gnu/packages/ghostscript.scm b/gnu/packages/ghostscript.scm
index 88f24209c8..0a65813f97 100644
--- a/gnu/packages/ghostscript.scm
+++ b/gnu/packages/ghostscript.scm
@@ -133,8 +133,8 @@ printing, and psresize, for adjusting page sizes.")
             (sha256
              (base32
               "0q4jj41p0qbr4mgcc9q78f5zs8cm1g57wgryhsm2yq4lfslm3ib1"))
-            (patches (map search-patch '("ghostscript-CVE-2015-3228.patch"
-                                         "ghostscript-runpath.patch")))
+            (patches (search-patches "ghostscript-CVE-2015-3228.patch"
+                                     "ghostscript-runpath.patch"))
             (modules '((guix build utils)))
             (snippet
              ;; Honor --docdir.
diff --git a/gnu/packages/gimp.scm b/gnu/packages/gimp.scm
index 00feb1c131..bd2794305b 100644
--- a/gnu/packages/gimp.scm
+++ b/gnu/packages/gimp.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -19,9 +20,11 @@
 (define-module (gnu packages gimp)
   #:use-module (guix packages)
   #:use-module (guix download)
+  #:use-module (guix utils)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system glib-or-gtk)
+  #:use-module (gnu packages algebra)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gtk)
@@ -157,3 +160,53 @@ retouching, composition and authoring.  It supports all common image formats
 as well as specialized ones.  It features a highly customizable interface
 that is extensible via a plugin system.")
     (license license:gpl3+))) ; some files are lgplv3
+
+(define-public gimp-fourier
+  (package
+    (name "gimp-fourier")
+    (version "0.4.3-2")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://registry.gimp.org/files/fourier-"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "1rpacyad678lqgxa3hh2n0zpg4azs8dpa8q079bqsl12812k9184"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f ;no tests
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)
+         (add-after 'unpack 'set-prefix
+           (lambda* (#:key outputs #:allow-other-keys)
+             ;; gimptool-2.0 does not allow us to install to any target
+             ;; directory.
+             (let ((target (string-append (assoc-ref outputs "out")
+                                          "/lib/gimp/"
+                                          (car (string-split ,(package-version gimp) #\.))
+                                          ".0/plug-ins")))
+               (substitute* "Makefile"
+                 (("\\$\\(PLUGIN_INSTALL\\) fourier")
+                  (string-append "cp fourier " target)))
+               (mkdir-p target))
+             #t)))))
+    (inputs
+     `(("fftw" ,fftw)
+       ("gimp" ,gimp)
+       ;; needed by gimp-2.0.pc
+       ("gdk-pixbuf" ,gdk-pixbuf)
+       ("cairo" ,cairo)
+       ("glib" ,glib)
+       ;; needed by gimpui-2.0.pc
+       ("gtk+" ,gtk+-2)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (home-page "http://registry.gimp.org/node/19596")
+    (synopsis "GIMP plug-in to edit image in fourier space")
+    (description
+     "This package provides a simple plug-in to apply the fourier transform on
+an image, allowing you to work with the transformed image inside GIMP.  You
+can draw or apply filters in fourier space and get the modified image with an
+inverse fourier transform.")
+    (license license:gpl3+)))
diff --git a/gnu/packages/glib.scm b/gnu/packages/glib.scm
index 16a1a6162d..e7e9df8dff 100644
--- a/gnu/packages/glib.scm
+++ b/gnu/packages/glib.scm
@@ -68,8 +68,7 @@
               (sha256
                (base32
                 "0jwj7wlrhq5y0fwfh8k2d9rgdpfax06lj8698g6iqbwrzd2rgyqx"))
-              (patches
-               (list (search-patch "dbus-helper-search-path.patch")))))
+              (patches (search-patches "dbus-helper-search-path.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags
@@ -139,11 +138,11 @@ shared NFS home directories.")
             (sha256
              (base32
               "1yzxr1ip3l0m9ydk5nq32piq70c9f17p5f0jyvlsghzbaawh67ss"))
-            (patches (list (search-patch "glib-tests-homedir.patch")
-                           (search-patch "glib-tests-desktop.patch")
-                           (search-patch "glib-tests-prlimit.patch")
-                           (search-patch "glib-tests-timer.patch")
-                           (search-patch "glib-tests-gapplication.patch")))))
+            (patches (search-patches "glib-tests-homedir.patch"
+                                     "glib-tests-desktop.patch"
+                                     "glib-tests-prlimit.patch"
+                                     "glib-tests-timer.patch"
+                                     "glib-tests-gapplication.patch"))))
    (build-system gnu-build-system)
    (outputs '("out"           ; everything
               "bin"           ; glib-mkenums, gtester, etc.; depends on Python
@@ -231,12 +230,10 @@ dynamic loading, and an object system.")
              (snippet
               '(substitute* "tools/g-ir-tool-template.in"
                  (("#!/usr/bin/env @PYTHON@") "#!@PYTHON@")))
-             (patches (list
-                       (search-patch "gobject-introspection-cc.patch")
-                       (search-patch
-                        "gobject-introspection-girepository.patch")
-                       (search-patch
-                        "gobject-introspection-absolute-shlib-path.patch")))))
+             (patches (search-patches
+                       "gobject-introspection-cc.patch"
+                       "gobject-introspection-girepository.patch"
+                       "gobject-introspection-absolute-shlib-path.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("bison" ,bison)
@@ -479,9 +476,8 @@ useful for C++.")
        (sha256
         (base32
          "1f5dfxjnil2glfwxnqr14d2cjfbkghsbsn8n04js2c2icr7iv2pv"))
-       (patches
-        (list (search-patch
-               "python2-pygobject-2-gi-info-type-error-domain.patch")))))
+       (patches (search-patches
+                 "python2-pygobject-2-gi-info-type-error-domain.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("which" ,which)
diff --git a/gnu/packages/gnome.scm b/gnu/packages/gnome.scm
index 5c2cf0197e..0fd1d5bb29 100644
--- a/gnu/packages/gnome.scm
+++ b/gnu/packages/gnome.scm
@@ -15,6 +15,7 @@
 ;;; Copyright © 2016 Rene Saavedra <rennes@openmailbox.org>
 ;;; Copyright © 2016 Jochem Raat <jchmrt@riseup.net>
 ;;; Copyright © 2016 Rene Saavedra <rennes@openmailbox.org>
+;;; Copyright © 2016 Kei Yamashita <kei@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -57,6 +58,7 @@
   #:use-module (gnu packages flex)
   #:use-module (gnu packages docbook)
   #:use-module (gnu packages enchant)
+  #:use-module (gnu packages game-development)
   #:use-module (gnu packages gettext)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gnupg)
@@ -737,8 +739,8 @@ the API.")
                                   version "/gtkglext-" version ".tar.gz"))
               (sha256
                (base32 "1ya4d2j2aacr9ii5zj4ac95fjpdvlm2rg79mgnk7yvl1dcy3y1z5"))
-              (patches (list
-                        (search-patch "gtkglext-disable-disable-deprecated.patch")))))
+              (patches (search-patches
+                        "gtkglext-disable-disable-deprecated.patch"))))
     (build-system gnu-build-system)
     (inputs `(("gtk+" ,gtk+-2)
               ("mesa" ,mesa)
@@ -1008,7 +1010,8 @@ featuring mature C, C++ and Python bindings.")
                                   "/" name "-" version ".tar.bz2"))
               (sha256
                (base32 "0swp4kk6x7hy1rvd1f9jba31lvfc6qvafkvbpg9h0r34fzrd8q4i"))
-              (patches (list (search-patch "libbonobo-activation-test-race.patch")))))
+              (patches (search-patches
+                        "libbonobo-activation-test-race.patch"))))
     (build-system gnu-build-system)
     (arguments
      ;; The programmer kindly gives us a hook to turn off deprecation warnings ...
@@ -1974,7 +1977,7 @@ library.")
                (base32
                 "1cchmi08jpjypgmm9i7xzh5qfg2q5k61kry9ns8mhw3z44a440ym"))
               (patches
-               (list (search-patch "glib-networking-ssl-cert-file.patch")))))
+               (search-patches "glib-networking-ssl-cert-file.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags
@@ -2207,6 +2210,41 @@ and other secrets.  It communicates with the \"Secret Service\" using DBus.")
 floating in an ocean using only your brain and a little bit of luck.")
     (license license:gpl2+)))
 
+(define-public gnome-sudoku
+  (package
+    (name "gnome-sudoku")
+    (version "3.18.2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "mirror://gnome/sources/" name "/"
+                           (version-major+minor version) "/"
+                           name "-" version ".tar.xz"))
+       (sha256
+        (base32
+         "1b60z22fjrjzsz0kfhv0kfhvigzn54wvh9s31zrlp7sx2h2dxvsf"))))
+    (build-system glib-or-gtk-build-system)
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("desktop-file-utils" ,desktop-file-utils)
+       ("intltool" ,intltool)
+       ("itstool" ,itstool)
+       ("xmllint" ,libxml2)))
+    (inputs
+     `(("gtk+" ,gtk+)
+       ("json-glib" ,json-glib)
+       ("libgee" ,libgee)
+       ("librsvg" ,librsvg)
+       ("qqwing" ,qqwing)))
+    (home-page "https://wiki.gnome.org/Apps/Sudoku")
+    (synopsis "Japanese logic game")
+    (description
+     "Sudoku is a Japanese logic game that exploded in popularity in 2005.
+GNOME Sudoku is meant to have an interface as simple and unobstrusive as
+possible while still providing features that make playing difficult Sudoku
+more fun.")
+    (license license:gpl2+)))
+
 (define-public gnome-terminal
   (package
     (name "gnome-terminal")
@@ -2334,7 +2372,7 @@ output devices.")
        (sha256
         (base32
          "0inlqx0zar498fhi9hh92p2g4kp8qy3zdl4z3vw6bjwp9w6xx454"))
-       (patches (list (search-patch "geoclue-config.patch")))))
+       (patches (search-patches "geoclue-config.patch"))))
     (build-system glib-or-gtk-build-system)
     (arguments
      '(;; The tests want to run the system bus.
@@ -2413,7 +2451,7 @@ faster results and to avoid unnecessary server load.")
               (sha256
                (base32
                 "0f6x9mi1jzgqdpycaikyhjljnw3aacsl3gxndyg0dfqkq6y9jwb9"))
-              (patches (list (search-patch "upower-builddir.patch")))))
+              (patches (search-patches "upower-builddir.patch"))))
     (build-system glib-or-gtk-build-system)
     (arguments
      '( ;; The tests want to contact the system bus, which can't be done in the
diff --git a/gnu/packages/gnucash.scm b/gnu/packages/gnucash.scm
index 58d3bda561..5c0ce4f544 100644
--- a/gnu/packages/gnucash.scm
+++ b/gnu/packages/gnucash.scm
@@ -47,7 +47,7 @@
       (sha256
        (base32
         "0x84f07p30pwhriamv8ifljgw755cj87rc12jy1xddf47spyj7rp"))
-      (patches (list (search-patch "gnucash-price-quotes-perl.patch")))))
+      (patches (search-patches "gnucash-price-quotes-perl.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("guile" ,guile-2.0)
diff --git a/gnu/packages/gnunet.scm b/gnu/packages/gnunet.scm
index 471f383b85..b5a2685f65 100644
--- a/gnu/packages/gnunet.scm
+++ b/gnu/packages/gnunet.scm
@@ -67,7 +67,7 @@
             (sha256
              (base32
               "0zvv7wd011npcx7yphw9bpgivyxz6mlp87a57n96nv85k96dd2l6"))
-            (patches (list (search-patch "libextractor-ffmpeg-3.patch")))
+            (patches (search-patches "libextractor-ffmpeg-3.patch"))
             (modules '((guix build utils)))
             (snippet
              ;; Nowadays libmagic (from 'file') returns 'audio/ogg' and not
diff --git a/gnu/packages/gnupg.scm b/gnu/packages/gnupg.scm
index 18ed6f9714..3f3964e74b 100644
--- a/gnu/packages/gnupg.scm
+++ b/gnu/packages/gnupg.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2013, 2015 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
@@ -66,7 +66,9 @@
 for all GnuPG components.  Among these are GPG, GPGSM, GPGME,
 GPG-Agent, libgcrypt, Libksba, DirMngr, Pinentry, SmartCard
 Daemon and possibly more in the future.")
-    (license license:lgpl2.0+)))
+    (license license:lgpl2.0+)
+    (properties '((ftp-server . "ftp.gnupg.org")
+                  (ftp-directory . "/gcrypt/libgpg-error")))))
 
 (define-public libgcrypt
   (package
@@ -100,7 +102,9 @@ Daemon and possibly more in the future.")
 standard cryptographic building blocks such as symmetric ciphers, hash
 algorithms, public key algorithms, large integer functions and random number
 generation.")
-    (license license:lgpl2.0+)))
+    (license license:lgpl2.0+)
+    (properties '((ftp-server . "ftp.gnupg.org")
+                  (ftp-directory . "/gcrypt/libgcrypt")))))
 
 (define-public libgcrypt-1.5
   (package (inherit libgcrypt)
@@ -137,7 +141,9 @@ generation.")
 protocol.  This protocol is used for IPC between most newer
 GnuPG components.  Both, server and client side functions are
 provided.")
-    (license license:lgpl2.0+)))
+    (license license:lgpl2.0+)
+    (properties '((ftp-server . "ftp.gnupg.org")
+                  (ftp-directory . "/gcrypt/libassuan")))))
 
 (define-public libksba
   (package
@@ -170,7 +176,9 @@ provided.")
      "KSBA (pronounced Kasbah) is a library to make X.509 certificates
 as well as the CMS easily accessible by other applications.  Both
 specifications are building blocks of S/MIME and TLS.")
-    (license license:gpl3+)))
+    (license license:gpl3+)
+    (properties '((ftp-server . "ftp.gnupg.org")
+                  (ftp-directory . "/gcrypt/libksba")))))
 
 (define-public npth
   (package
@@ -208,9 +216,8 @@ compatible to GNU Pth.")
               (sha256
                (base32
                 "06mn2viiwsyq991arh5i5fhr9jyxq2bi0jkdj7ndfisxihngpc5p"))
-              (patches
-               (list (search-patch
-                      "gnupg-simple-query-ignore-status-messages.patch")))))
+              (patches (search-patches
+                        "gnupg-simple-query-ignore-status-messages.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
@@ -245,7 +252,9 @@ features powerful key management and the ability to access public key
 servers.  It includes several libraries: libassuan (IPC between GnuPG
 components), libgpg-error (centralized GnuPG error values), and
 libskba (working with X.509 certificates and CMS data).")
-    (license license:gpl3+)))
+    (license license:gpl3+)
+    (properties '((ftp-server . "ftp.gnupg.org")
+                  (ftp-directory . "/gcrypt/gnupg")))))
 
 (define-public gnupg-2.0
   (package (inherit gnupg)
@@ -352,7 +361,7 @@ and every application benefits from this.")
        ;; Unfortunately, we have to disable some tests due to some gpg-agent
        ;; goofiness... see:
        ;;   https://bugs.launchpad.net/pygpgme/+bug/999949
-       (patches (list (search-patch "pygpgme-disable-problematic-tests.patch")))))
+       (patches (search-patches "pygpgme-disable-problematic-tests.patch"))))
     (arguments
      `(#:phases
        (modify-phases %standard-phases
@@ -563,14 +572,14 @@ including tools for signing keys, keyring analysis, and party preparation.
 (define-public pinentry
   (package
     (name "pinentry")
-    (version "0.9.6")
+    (version "0.9.7")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://gnupg/pinentry/pinentry-"
                                   version ".tar.bz2"))
               (sha256
                (base32
-                "0rhyw1vk28kgasjp22myf7m2q8kycw82d65pr9kgh93z17lj849a"))))
+                "1cp7wjqr6nx31mdclr61s2h84ijqjl0ph99kgj4vyawpjj1j1633"))))
     (build-system gnu-build-system)
     (inputs
      `(("ncurses" ,ncurses)
@@ -580,7 +589,7 @@ including tools for signing keys, keyring analysis, and party preparation.
        ("glib" ,glib)))
     (native-inputs
      `(("pkg-config" ,pkg-config)))
-    (home-page "http://gnupg.org/aegypten2/")
+    (home-page "https://gnupg.org/aegypten2/")
     (synopsis "GnuPG's interface to passphrase input")
     (description
      "Pinentry provides a console and a GTK+ GUI that allows users to
diff --git a/gnu/packages/gnustep.scm b/gnu/packages/gnustep.scm
index ae97eb7936..f4a2b266a3 100644
--- a/gnu/packages/gnustep.scm
+++ b/gnu/packages/gnustep.scm
@@ -127,3 +127,92 @@ of battery life remain, battery life remaining (with both a percentage and a
 graph), and battery status (high - green, low - yellow, or critical - red).")
     (license gpl2)))
 
+(define-public wmnd
+  (package
+    (name "wmnd")
+    (version "0.4.17")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "http://www.thregr.org/~wavexx/software/wmnd/releases/"
+                    name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1amkbiwgr31gwkcp7wrjsr7aj1kns8bpmjpv70n86wb8v9mpm828"))))
+    (build-system gnu-build-system)
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)
+       ("libxpm" ,libxpm)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (home-page "http://www.thregr.org/~wavexx/software/wmnd/")
+    (synopsis "Network interface monitor")
+    (description
+     "WMND is a dockapp for monitoring network interfaces under WindowMaker and
+other compatible window managers.")
+    (license gpl2+)))
+
+(define-public wmcpuload
+  (package
+    (name "wmcpuload")
+    (version "1.0.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "mirror://debian/pool/main/w/wmcpuload/"
+                    name "_" version ".orig.tar.gz"))
+              (sha256
+               (base32
+                "0irlns4cvxy2mnicx75bya166hdxq7h8bphds3ligijcl9fzgs6n"))))
+    (build-system gnu-build-system)
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)
+       ("libxpm" ,libxpm)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (home-page "http://windowmaker.org/dockapps/?name=wmcpuload")
+    (synopsis "Monitor CPU usage")
+    (description
+     "Wmcpuload displays the current CPU usage, expressed as a percentile and a
+chart, and has an LCD look-alike user interface.  The back-light may be turned
+on and off by clicking the mouse button over the application.  If the CPU usage
+hits a certain threshold, an alarm-mode will alert you by turning back-light
+on.")
+    (license gpl2+)))
+
+(define-public wmclock
+  (package
+    (name "wmclock")
+    (version "1.0.16")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "mirror://debian/pool/main/w/wmclock/"
+                    name "_" version ".orig.tar.gz"))
+              (sha256
+               (base32
+                "1lx276ba8r2yydhmwj1g586jdqg695ad89ng36fr3mb067gvb2rz"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'autoconf
+           (lambda _ (zero? (system* "autoreconf" "-vfi")))))))
+    ;; wmclock requires autoreconf to generate its configure script.
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)
+       ("libxpm" ,libxpm)))
+    (native-inputs
+     `(("autoconf" ,autoconf)
+       ("automake" ,automake)
+       ("pkg-config" ,pkg-config)))
+    (home-page "http://windowmaker.org/dockapps/?name=wmclock")
+    (synopsis "Display the date and time")
+    (description
+     "wmclock is an applet for Window Maker which displays the date and time in
+a dockable tile.  It features multiple language support, 24h or 12h time
+display, and can run a user-specified program on mouse click.")
+    (license gpl2+)))
diff --git a/gnu/packages/gnuzilla.scm b/gnu/packages/gnuzilla.scm
index b4892d77cd..abefd90304 100644
--- a/gnu/packages/gnuzilla.scm
+++ b/gnu/packages/gnuzilla.scm
@@ -1,8 +1,9 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2015 Andreas Enge <andreas@enge.fr>
-;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -143,7 +144,7 @@ in C/C++.")
 (define-public nspr
   (package
     (name "nspr")
-    (version "4.10.10")
+    (version "4.12")
     (source (origin
              (method url-fetch)
              (uri (string-append
@@ -151,7 +152,7 @@ in C/C++.")
                    version "/src/nspr-" version ".tar.gz"))
              (sha256
               (base32
-               "01ria9wk6329hxqsy75p9dkxiqkq4nkz0jjzll7hslih3jbi8dil"))))
+               "1pk98bmc5xzbl62q5wf2d6mryf0v95z6rsmxz27nclwiaqg0mcg0"))))
     (build-system gnu-build-system)
     (native-inputs
       `(("perl" ,perl)))
@@ -177,7 +178,7 @@ in the Mozilla clients.")
 (define-public nss
   (package
     (name "nss")
-    (version "3.21.1")
+    (version "3.23")
     (source (origin
               (method url-fetch)
               (uri (let ((version-with-underscores
@@ -188,9 +189,9 @@ in the Mozilla clients.")
                       "nss-" version ".tar.gz")))
               (sha256
                (base32
-                "0knr99yc8sba2ga6x1gwhg9gr1dmgcl344g3bmxm8c364i2vpxns"))
+                "1kqidv91icq96m9m8zx50n7px08km2l88458rkgyjwcn3kiq7cwl"))
               ;; Create nss.pc and nss-config.
-              (patches (list (search-patch "nss-pkgconfig.patch")))))
+              (patches (search-patches "nss-pkgconfig.patch"))))
     (build-system gnu-build-system)
     (outputs '("out" "bin"))
     (arguments
@@ -250,7 +251,16 @@ in the Mozilla clients.")
               ;; Install other files.
               (copy-recursively "dist/public/nss" inc)
               (copy-recursively (string-append obj "/bin") bin)
-              (copy-recursively (string-append obj "/lib") lib)))
+              (copy-recursively (string-append obj "/lib") lib)
+
+              ;; FIXME: libgtest1.so is installed in the above step, and it's
+              ;; (unnecessarily) linked with several NSS libraries, but
+              ;; without the needed rpaths, causing the 'validate-runpath'
+              ;; phase to fail.  Here we simply delete libgtest1.so, since it
+              ;; seems to be used only during the tests.
+              (delete-file (string-append lib "/libgtest1.so"))
+
+              #t))
           %standard-phases)))))
     (inputs
      `(("sqlite" ,sqlite)
@@ -277,7 +287,7 @@ standards.")
 (define-public icecat
   (package
     (name "icecat")
-    (version "38.6.0-gnu1")
+    (version "38.7.1-gnu1")
     (source
      (origin
       (method url-fetch)
@@ -286,29 +296,19 @@ standards.")
                           name "-" version ".tar.bz2"))
       (sha256
        (base32
-        "0bd4k5cwr8ynscaxffvj2x3kgky3dmjq0qhpcb931l98bh0103lx"))
-      (patches (map search-patch
-                    '("icecat-avoid-bundled-includes.patch"
-                      "icecat-re-enable-DHE-cipher-suites.patch"
-                      "icecat-update-graphite2.patch"
-                      "icecat-update-graphite2-pt2.patch"
-                      "icecat-CVE-2015-4477.patch"
-                      "icecat-CVE-2015-7207.patch"
-                      "icecat-CVE-2016-1952-pt01.patch"
-                      "icecat-CVE-2016-1952-pt02.patch"
-                      "icecat-CVE-2016-1952-pt03.patch"
-                      "icecat-CVE-2016-1952-pt04.patch"
-                      "icecat-CVE-2016-1952-pt05.patch"
-                      "icecat-CVE-2016-1952-pt06.patch"
-                      "icecat-CVE-2016-1954.patch"
-                      "icecat-CVE-2016-1960.patch"
-                      "icecat-CVE-2016-1961.patch"
-                      "icecat-CVE-2016-1962.patch"
-                      "icecat-CVE-2016-1964.patch"
-                      "icecat-CVE-2016-1965.patch"
-                      "icecat-CVE-2016-1966.patch"
-                      "icecat-CVE-2016-1974.patch"
-                      "icecat-bug-1248851.patch")))
+        "1wdmd6hasra36g86ha1dw8sl7a5mvr7c4jbjx4zyg9629y5gqr8g"))
+      (patches (search-patches
+                "icecat-avoid-bundled-includes.patch"
+                "icecat-re-enable-DHE-cipher-suites.patch"
+                "icecat-update-bundled-graphite2.patch"
+                "icecat-CVE-2016-2805.patch"
+                "icecat-CVE-2016-2807-pt1.patch"
+                "icecat-CVE-2016-2807-pt2.patch"
+                "icecat-CVE-2016-2807-pt3.patch"
+                "icecat-CVE-2016-2807-pt4.patch"
+                "icecat-CVE-2016-2807-pt5.patch"
+                "icecat-CVE-2016-2808.patch"
+                "icecat-CVE-2016-2814.patch"))
       (modules '((guix build utils)))
       (snippet
        '(begin
@@ -526,4 +526,5 @@ standards.")
      "IceCat is the GNU version of the Firefox browser.  It is entirely free
 software, which does not recommend non-free plugins and addons.  It also
 features built-in privacy-protecting features.")
-    (license license:mpl2.0))) ; and others, see toolkit/content/license.html
+    (license license:mpl2.0)     ;and others, see toolkit/content/license.html
+    (properties '((ftp-directory . "/gnu/gnuzilla")))))
diff --git a/gnu/packages/graphics.scm b/gnu/packages/graphics.scm
index 6edba5025d..f46dee36d2 100644
--- a/gnu/packages/graphics.scm
+++ b/gnu/packages/graphics.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Tomáš Čech <sleep_walker@gnu.org>
 ;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
@@ -31,9 +31,13 @@
   #:use-module (gnu packages audio)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages bash)
+  #:use-module (gnu packages bison)
   #:use-module (gnu packages boost)
+  #:use-module (gnu packages doxygen)
+  #:use-module (gnu packages haskell)
   #:use-module (gnu packages image)
   #:use-module (gnu packages python)
+  #:use-module (gnu packages flex)
   #:use-module (gnu packages fontutils)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages pulseaudio)  ;libsndfile, libsamplerate
@@ -41,13 +45,19 @@
   #:use-module (gnu packages multiprecision)
   #:use-module (gnu packages boost)
   #:use-module (gnu packages gl)
+  #:use-module (gnu packages glib)
+  #:use-module (gnu packages graphviz)
+  #:use-module (gnu packages gtk)
+  #:use-module (gnu packages gnome)
   #:use-module (gnu packages image)
   #:use-module (gnu packages jemalloc)
   #:use-module (gnu packages photo)
   #:use-module (gnu packages python)
   #:use-module (gnu packages qt)
+  #:use-module (gnu packages readline)
   #:use-module (gnu packages sdl)
   #:use-module (gnu packages video)
+  #:use-module (gnu packages xml)
   #:use-module (gnu packages xorg))
 
 (define-public blender
@@ -108,7 +118,7 @@
        ("libjpeg" ,libjpeg)
        ("libpng" ,libpng)
        ("libtiff" ,libtiff)
-       ("ffmpeg" ,ffmpeg)
+       ("ffmpeg-2.8" ,ffmpeg-2.8) ;<https://lists.gnu.org/archive/html/guix-devel/2016-04/msg01019.html>
        ("fftw" ,fftw)
        ("jack" ,jack-1)
        ("libsndfile" ,libsndfile)
@@ -176,7 +186,7 @@ many more.")
               (sha256
                (base32
                 "1izddjwbh1grs8080vmaix72z469qy29wrvkphgmqmcm0sv1by7c"))
-              (patches (map search-patch '("ilmbase-fix-tests.patch")))))
+              (patches (search-patches "ilmbase-fix-tests.patch"))))
     (build-system gnu-build-system)
     (home-page "http://www.openexr.com/")
     (synopsis "Utility C++ libraries for threads, maths, and exceptions")
@@ -204,7 +214,7 @@ exception-handling library.")
                '(substitute* (find-files "." "tmpDir\\.h")
                   (("\"/var/tmp/\"")
                    "\"/tmp/\"")))
-              (patches (list (search-patch "openexr-missing-samples.patch")))))
+              (patches (search-patches "openexr-missing-samples.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases
@@ -245,7 +255,7 @@ storage of the \"EXR\" file format for storing 16-bit floating-point images.")
               (sha256
                (base32
                 "0mn7cz19mn8dcrhkq15h25gl20ammr1wz0j2j3c2vxs6ph7zn8jy"))
-              (patches (list (search-patch "openimageio-boost-1.60.patch")))))
+              (patches (search-patches "openimageio-boost-1.60.patch"))))
     (build-system cmake-build-system)
     ;; FIXME: To run all tests successfully, test image sets from multiple
     ;; third party sources have to be present.  For details see
@@ -272,6 +282,59 @@ visual effects work for film.")
     (home-page "http://www.openimageio.org")
     (license license:bsd-3)))
 
+(define-public rapicorn
+  (package
+    (name "rapicorn")
+    (version "16.0.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://testbit.eu/pub/dists/rapicorn/"
+                                  "rapicorn-" version ".tar.xz"))
+              (sha256
+               (base32
+                "1y51yjrpsihas1jy905m9p3r8iiyhq6bwi2690c564i5dnix1f9d"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(;; FIXME: At least "testrcore1" fails.
+       #:tests? #f
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'replace-/bin/ls
+           (lambda _
+             (substitute* (cons "Makefile.decl"
+                                (find-files "." "^Makefile\\.in$"))
+               (("/bin/ls") (which "ls")))
+             #t)))))
+    ;; These libraries are listed in the "Required" section of the pkg-config
+    ;; file.
+    (propagated-inputs
+     `(("librsvg" ,librsvg)
+       ("cairo" ,cairo)
+       ("pango" ,pango)
+       ("libxml2" ,libxml2)))
+    (inputs
+     `(("gdk-pixbuf" ,gdk-pixbuf)
+       ("libpng" ,libpng-1.2)
+       ("readline" ,readline)
+       ("libcroco" ,libcroco)
+       ("python" ,python-2)
+       ("cython" ,python2-cython)))
+    (native-inputs
+     `(("pandoc" ,ghc-pandoc)
+       ("bison" ,bison)
+       ("flex" ,flex)
+       ("doxygen" ,doxygen)
+       ("graphviz" ,graphviz)
+       ("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)))
+    (home-page "http://rapicorn.org")
+    (synopsis "Toolkit for rapid development of user interfaces")
+    (description
+     "Rapicorn is a toolkit for rapid development of user interfaces in C++
+and Python.  The user interface is designed in a declarative markup language
+and is connected to the programming logic using data bindings and commands.")
+    (license license:mpl2.0)))
+
 (define-public ctl
   (package
     (name "ctl")
@@ -385,7 +448,7 @@ and understanding different BRDFs (and other component functions).")
                                         version ".tar.gz")))
               (sha256
                (base32 "07wii4i824vy9qsvjsgqxppgqmfdxq0xa87i5yk53fijriadq7mb"))
-              (patches (list (search-patch "agg-am_c_prototype.patch")))))
+              (patches (search-patches "agg-am_c_prototype.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags
diff --git a/gnu/packages/grub.scm b/gnu/packages/grub.scm
index 96d284c108..5fc7ee8386 100644
--- a/gnu/packages/grub.scm
+++ b/gnu/packages/grub.scm
@@ -83,9 +83,9 @@
              (sha256
               (base32
                "0n64hpmsccvicagvr0c6v0kgp2yw0kgnd3jvsyd26cnwgs7c6kkq"))
-             (patches (list (search-patch "grub-gets-undeclared.patch")
-                            (search-patch "grub-freetype.patch")
-                            (search-patch "grub-CVE-2015-8370.patch")))))
+             (patches (search-patches "grub-gets-undeclared.patch"
+                                      "grub-freetype.patch"
+                                      "grub-CVE-2015-8370.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags '("--disable-werror")
diff --git a/gnu/packages/gtk.scm b/gnu/packages/gtk.scm
index 3bc4b8dc07..255d885b27 100644
--- a/gnu/packages/gtk.scm
+++ b/gnu/packages/gtk.scm
@@ -554,7 +554,7 @@ is part of the GNOME accessibility project.")
             (sha256
              (base32
               "0mj6xn40py9r9lvzg633fal81xfwfm89d9mvz7jk4lmwk0g49imj"))
-            (patches (list (search-patch "gtk2-respect-GUIX_GTK2_PATH.patch")))))
+            (patches (search-patches "gtk2-respect-GUIX_GTK2_PATH.patch"))))
    (build-system gnu-build-system)
    (outputs '("out" "doc"))
    (propagated-inputs
@@ -615,7 +615,7 @@ application suites.")
             (sha256
              (base32
               "0lp1hn0qydxx03bianzzr0a4maqzsvylrkzr7c3p0050qihwbgjx"))
-            (patches (list (search-patch "gtk3-respect-GUIX_GTK3_PATH.patch")))))
+            (patches (search-patches "gtk3-respect-GUIX_GTK3_PATH.patch"))))
    (propagated-inputs
     `(("at-spi2-atk" ,at-spi2-atk)
       ("atk" ,atk)
@@ -752,7 +752,7 @@ exceptions, macros, and a dynamic programming environment.")
               (sha256
                (base32
                 "136f236iw3yrrz6pkkp1ma9c5mrs5icqha6pnawinqpk892r3jh7"))
-              (patches (list (search-patch "guile-rsvg-pkgconfig.patch")))
+              (patches (search-patches "guile-rsvg-pkgconfig.patch"))
               (modules '((guix build utils)))
               (snippet
                '(substitute* (find-files "." "Makefile\\.am")
@@ -791,7 +791,7 @@ images onto Cairo surfaces.")
               (sha256
                (base32
                 "1qam447m05sxxv6x8dlzg7qnyfc4dh8apjw1idpfhpns671gfr6m"))
-              (patches (list (search-patch "guile-present-coding.patch")))
+              (patches (search-patches "guile-present-coding.patch"))
               (modules '((guix build utils)))
               (snippet
                '(substitute* "Makefile.in"
@@ -977,7 +977,7 @@ extensive documentation, including API reference and a tutorial.")
       (sha256
        (base32
         "1gjkf8x6hyx1skq3hhwcbvwifxvrf9qxis5vx8x5igmmgs70g94s"))
-      (patches (list (search-patch "pycairo-wscript.patch")))))
+      (patches (search-patches "pycairo-wscript.patch"))))
     (build-system waf-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
diff --git a/gnu/packages/guile.scm b/gnu/packages/guile.scm
index fe043cba0b..53ea3e53bb 100644
--- a/gnu/packages/guile.scm
+++ b/gnu/packages/guile.scm
@@ -4,6 +4,7 @@
 ;;; Copyright © 2015 Christopher Allan Webber <cwebber@dustycloud.org>
 ;;; Copyright © 2016 Alex Sassmannshausen <alex@pompo.co>
 ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2016 Erik Edrosa <erik.edrosa@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -72,7 +73,7 @@
             (sha256
              (base32
               "0l200a0v7h8bh0cwz6v7hc13ds39cgqsmfrks55b1rbj5vniyiy3"))
-            (patches (list (search-patch "guile-1.8-cpp-4.5.patch")))))
+            (patches (search-patches "guile-1.8-cpp-4.5.patch"))))
    (build-system gnu-build-system)
    (arguments '(#:configure-flags '("--disable-error-on-warning")
 
@@ -132,7 +133,7 @@ without requiring the source code to be rewritten.")
             (sha256
              (base32
               "1qh3j7308qvsjgwf7h94yqgckpbgz2k3yqdkzsyhqcafvfka9l5f"))
-            (patches (list (search-patch "guile-arm-fixes.patch")))))
+            (patches (search-patches "guile-arm-fixes.patch"))))
    (build-system gnu-build-system)
    (native-inputs `(("pkgconfig" ,pkg-config)))
    (inputs `(("libffi" ,libffi)
@@ -410,7 +411,7 @@ library.")
              (sha256
               (base32
                "0zparwgf01jgl1x53ik71ghabldq6zz18ha4dscps1i0qrzgap1b"))
-             (patches (list (search-patch "mcron-install.patch")))))
+             (patches (search-patches "mcron-install.patch"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)))
     (inputs `(("ed" ,ed) ("which" ,which) ("guile" ,guile-2.0)))
@@ -529,7 +530,7 @@ http:://json.org specification.  These are the main features:
            (setenv "GUILE_AUTO_COMPILE" "0")
            (for-each (lambda (file)
                        (let* ((dest-file (string-append module-dir "/"
-                                                        file ".scm"))
+                                                        file))
                               (go-file (match (string-split file #\.)
                                          ((base _)
                                           (string-append module-dir "/"
@@ -711,14 +712,14 @@ Guile's foreign function interface.")
 (define-public haunt
   (package
     (name "haunt")
-    (version "0.1")
+    (version "0.2")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://files.dthompson.us/haunt/haunt-"
+              (uri (string-append "https://files.dthompson.us/haunt/haunt-"
                                   version ".tar.gz"))
               (sha256
                (base32
-                "15q1qwjnay7k90ppqrzqsmikvwyj61mjvf1zahyd9gm4vi2fgb3x"))))
+                "1id83n8fs7jxys1d8jy70vylg8gzcvlw1y7hb41y3qxv5zi4671m"))))
     (build-system gnu-build-system)
     (arguments
      `(#:modules ((ice-9 match) (ice-9 ftw)
@@ -742,8 +743,13 @@ Guile's foreign function interface.")
                                `("GUILE_LOAD_COMPILED_PATH" ":" prefix
                                  (,modules)))
                              #t)))))))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("texinfo" ,texinfo)))
     (inputs
      `(("guile" ,guile-2.0)))
+    (propagated-inputs
+     `(("guile-reader" ,guile-reader)))
     (synopsis "Functional static site generator")
     (description "Haunt is a static site generator written in Guile
 Scheme.  Haunt features a functional build system and an extensible
diff --git a/gnu/packages/ibus.scm b/gnu/packages/ibus.scm
index 770d7ff067..db7d084fc7 100644
--- a/gnu/packages/ibus.scm
+++ b/gnu/packages/ibus.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -24,10 +25,12 @@
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system glib-or-gtk)
   #:use-module (gnu packages)
+  #:use-module (gnu packages anthy)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages base)
   #:use-module (gnu packages databases)
   #:use-module (gnu packages freedesktop)
+  #:use-module (gnu packages gettext)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gnome)
   #:use-module (gnu packages gtk)
@@ -205,3 +208,54 @@ ZhuYin (Bopomofo) input method based on libpinyin for IBus.")
 Chinese pinyin input methods.")
     (home-page "https://github.com/libpinyin/libpinyin")
     (license gpl2+)))
+
+(define-public ibus-anthy
+  (package
+    (name "ibus-anthy")
+    (version "1.5.8")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/ibus/ibus-anthy/releases/download/"
+                    version "/ibus-anthy-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1aj7vnfky7izl23xyjky78z3qas3q72l3kr8dnql2lnivsrb8q1y"))))
+    (build-system gnu-build-system)
+    (arguments
+     '(#:configure-flags
+       ;; Use absolute exec path in the anthy.xml.
+       (list (string-append "--libexecdir=" %output "/libexec"))
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'install 'wrap-programs
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out")))
+               (for-each
+                (lambda (prog)
+                  (wrap-program (string-append out "/libexec/" prog)
+                    `("PYTHONPATH" ":" prefix
+                      (,(getenv "PYTHONPATH")))
+                    `("GI_TYPELIB_PATH" ":" prefix
+                      (,(getenv "GI_TYPELIB_PATH")
+                       ,(string-append out "/lib/girepository-1.0")))))
+                '("ibus-engine-anthy" "ibus-setup-anthy"))
+               #t))))))
+    (native-inputs
+     `(("gettext" ,gnu-gettext)
+       ("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)
+       ("python" ,python)))
+    (inputs
+     `(("anthy" ,anthy)
+       ("gtk+" ,gtk+)
+       ("ibus" ,ibus)
+       ("gobject-introspection" ,gobject-introspection)
+       ("python-pygobject" ,python-pygobject)))
+    (synopsis "Anthy Japanese language input method for IBus")
+    (description "IBus-Anthy is an engine for the input bus \"IBus\").  It
+adds the Anthy Japanese language input method to IBus.  Because most graphical
+applications allow text input via IBus, installing this package will enable
+Japanese language input in most graphical applications.")
+    (home-page "https://github.com/fujiwarat/ibus-anthy")
+    (license gpl2+)))
diff --git a/gnu/packages/icu4c.scm b/gnu/packages/icu4c.scm
index a6f5acd4f2..fb33c761de 100644
--- a/gnu/packages/icu4c.scm
+++ b/gnu/packages/icu4c.scm
@@ -39,9 +39,9 @@
                   "-src.tgz"))
             (sha256
              (base32 "0ys5f5spizg45qlaa31j2lhgry0jka2gfha527n4ndfxxz5j4sz1"))
-            (patches (map search-patch '("icu4c-CVE-2014-6585.patch"
-                                         "icu4c-CVE-2015-1270.patch"
-                                         "icu4c-CVE-2015-4760.patch")))))
+            (patches (search-patches "icu4c-CVE-2014-6585.patch"
+                                     "icu4c-CVE-2015-1270.patch"
+                                     "icu4c-CVE-2015-4760.patch"))))
    (build-system gnu-build-system)
    (inputs
     `(("perl" ,perl)))
diff --git a/gnu/packages/idutils.scm b/gnu/packages/idutils.scm
index 3dc322f568..7a8e1c6752 100644
--- a/gnu/packages/idutils.scm
+++ b/gnu/packages/idutils.scm
@@ -35,8 +35,7 @@
              (sha256
               (base32
                "1hmai3422iaqnp34kkzxdnywl7n7pvlxp11vrw66ybxn9wxg90c1"))
-             (patches (list
-                       (search-patch "diffutils-gets-undeclared.patch")))))
+             (patches (search-patches "diffutils-gets-undeclared.patch"))))
     (build-system gnu-build-system)
     (native-inputs `(("emacs" ,emacs-no-x)))
     (home-page "http://www.gnu.org/software/idutils/")
diff --git a/gnu/packages/image.scm b/gnu/packages/image.scm
index 2273e78d8a..669ad5b938 100644
--- a/gnu/packages/image.scm
+++ b/gnu/packages/image.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2013, 2015, 2016 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
-;;; Copyright © 2014 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2014, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
 ;;; Copyright © 2015 Amirouche Boubekki <amirouche@hypermove.net>
 ;;; Copyright © 2014 John Darrington <jmd@gnu.org>
@@ -76,6 +76,22 @@ library.  It supports almost all PNG features and is extensible.")
    (license license:zlib)
    (home-page "http://www.libpng.org/pub/png/libpng.html")))
 
+(define-public libpng-1.2
+  (package
+    (inherit libpng)
+    (version "1.2.56")
+    (source
+     (origin
+       (method url-fetch)
+       ;; Note: upstream removes older tarballs.
+       (uri (list (string-append "mirror://sourceforge/libpng/libpng12/"
+                                 version "/libpng-" version ".tar.xz")
+                  (string-append
+                   "ftp://ftp.simplesystems.org/pub/libpng/png/src"
+                   "/libpng12/libpng-" version ".tar.xz")))
+       (sha256
+        (base32 "1ghd03p353x0vi4dk83n1nlldg11w7vqdk3f99rkgfb82ic59ki4"))))))
+
 (define-public libjpeg
   (package
    (name "libjpeg")
@@ -140,10 +156,10 @@ maximum quality factor.")
                    version ".tar.gz"))
             (sha256 (base32
                      "136nf1rj9dp5jgv1p7z4dk0xy3wki1w0vfjbk82f645m0w4samsd"))
-            (patches (map search-patch
-                          '("libtiff-oob-accesses-in-decode.patch"
-                            "libtiff-oob-write-in-nextdecode.patch"
-                            "libtiff-CVE-2015-8665+CVE-2015-8683.patch")))))
+            (patches (search-patches
+                      "libtiff-oob-accesses-in-decode.patch"
+                      "libtiff-oob-write-in-nextdecode.patch"
+                      "libtiff-CVE-2015-8665+CVE-2015-8683.patch"))))
    (build-system gnu-build-system)
    (outputs '("out"
               "doc"))                           ;1.3 MiB of HTML documentation
@@ -178,18 +194,18 @@ collection of tools for doing simple manipulations of TIFF images.")
         (sha256
          (base32 "1y3wba4q8pl7kr51212jwrsz1x6nslsx1gsjml1x0i8549lmqd2v"))
         (patches
-         (map search-patch '("libwmf-CAN-2004-0941.patch"
-                             "libwmf-CVE-2006-3376.patch"
-                             "libwmf-CVE-2007-0455.patch"
-                             "libwmf-CVE-2007-2756.patch"
-                             "libwmf-CVE-2007-3472.patch"
-                             "libwmf-CVE-2007-3473.patch"
-                             "libwmf-CVE-2007-3477.patch"
-                             "libwmf-CVE-2009-1364.patch"
-                             "libwmf-CVE-2009-3546.patch"
-                             "libwmf-CVE-2015-0848+CVE-2015-4588.patch"
-                             "libwmf-CVE-2015-4695.patch"
-                             "libwmf-CVE-2015-4696.patch")))))
+         (search-patches "libwmf-CAN-2004-0941.patch"
+                         "libwmf-CVE-2006-3376.patch"
+                         "libwmf-CVE-2007-0455.patch"
+                         "libwmf-CVE-2007-2756.patch"
+                         "libwmf-CVE-2007-3472.patch"
+                         "libwmf-CVE-2007-3473.patch"
+                         "libwmf-CVE-2007-3477.patch"
+                         "libwmf-CVE-2009-1364.patch"
+                         "libwmf-CVE-2009-3546.patch"
+                         "libwmf-CVE-2015-0848+CVE-2015-4588.patch"
+                         "libwmf-CVE-2015-4695.patch"
+                         "libwmf-CVE-2015-4696.patch"))))
 
     (build-system gnu-build-system)
     (inputs
@@ -291,7 +307,7 @@ arithmetic ops.")
                           version ".tar.gz"))
         (sha256
           (base32 "1ffhgmf2fqzk0h4k736pp06z7q5y4x41fg844bd6a9vgncq86bby"))
-        (patches (list (search-patch "jbig2dec-ignore-testtest.patch")))))
+        (patches (search-patches "jbig2dec-ignore-testtest.patch"))))
 
     (build-system gnu-build-system)
     (synopsis "Decoder of the JBIG2 image compression format")
@@ -320,8 +336,8 @@ work.")
                         version ".tar.gz"))
         (sha256
          (base32 "00zzm303zvv4ijzancrsb1cqbph3pgz0nky92k9qx3fq9y0vnchj"))
-        (patches (map search-patch '("openjpeg-use-after-free-fix.patch"
-                                     "openjpeg-CVE-2015-6581.patch")))))
+        (patches (search-patches "openjpeg-use-after-free-fix.patch"
+                                 "openjpeg-CVE-2015-6581.patch"))))
     (build-system cmake-build-system)
     (arguments
       ;; Trying to run `$ make check' results in a no rule fault.
@@ -357,8 +373,8 @@ error-resilience, a Java-viewer for j2k-images, ...")
                        version ".tar.gz"))
        (sha256
         (base32 "1c2xc3nl2mg511b63rk7hrckmy14681p1m44mzw3n1fyqnjm0b0z"))
-       (patches (map search-patch '("openjpeg-use-after-free-fix.patch"
-                                    "openjpeg-CVE-2015-6581.patch")))))))
+       (patches (search-patches "openjpeg-use-after-free-fix.patch"
+                                "openjpeg-CVE-2015-6581.patch"))))))
 
 (define-public openjpeg-1
   (package (inherit openjpeg)
@@ -443,7 +459,7 @@ compose, and analyze GIF images.")
 (define-public imlib2
   (package
     (name "imlib2")
-    (version "1.4.7")
+    (version "1.4.8")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -451,7 +467,8 @@ compose, and analyze GIF images.")
                     version ".tar.bz2"))
               (sha256
                (base32
-                "00a7jbwj10x3jcvxa5rplnkvhv35gv9rb400zy636zdd4g737mrm"))))
+                "0xxhgkd1axlcmf3kp1d7naiygparpg8l3sg3d263rhl2z0gm7aw9"))
+              (patches (search-patches "imlib2-CVE-2016-4024.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkgconfig" ,pkg-config)))
@@ -520,7 +537,7 @@ supplies a generic doubly-linked list and some string functions.")
             (sha256
              (base32
               "12bz57asdcfsz3zr9i9nska0fb6h3z2aizy412qjqkixkginbz7v"))
-            (patches (list (search-patch "freeimage-CVE-2015-0852.patch")))))
+            (patches (search-patches "freeimage-CVE-2015-0852.patch"))))
    (build-system gnu-build-system)
    (arguments
     '(#:phases (alist-delete
@@ -673,7 +690,7 @@ channels.")
                 "1zd850nn7nvkkhasrv7kn17kzgslr5ry933v6db62s4lr0zzlbv8"))
               ;; Backported from upstream:
               ;; https://github.com/DentonW/DevIL/commit/724194d7a9a91221a564579f64bdd6f0abd64219.patch
-              (patches (list (search-patch "devil-fix-libpng.patch")))
+              (patches (search-patches "devil-fix-libpng.patch"))
               (modules '((guix build utils)))
               (snippet
                ;; Fix old lcms include directives and lib flags.
@@ -723,21 +740,20 @@ convert, manipulate, filter and display a wide variety of image formats.")
               (sha256
                (base32
                 "154l7zk7yh3v8l2l6zm5s2alvd2fzkp6c9i18iajfbna5af5m43b"))
-              (patches
-                (list
-                  (search-patch "jasper-CVE-2007-2721.patch")
-                  (search-patch "jasper-CVE-2008-3520.patch")
-                  (search-patch "jasper-CVE-2008-3522.patch")
-                  (search-patch "jasper-CVE-2011-4516-and-CVE-2011-4517.patch")
-                  (search-patch "jasper-CVE-2014-8137.patch")
-                  (search-patch "jasper-CVE-2014-8138.patch")
-                  (search-patch "jasper-CVE-2014-8157.patch")
-                  (search-patch "jasper-CVE-2014-8158.patch")
-                  (search-patch "jasper-CVE-2014-9029.patch")
-                  (search-patch "jasper-CVE-2016-1577.patch")
-                  (search-patch "jasper-CVE-2016-1867.patch")
-                  (search-patch "jasper-CVE-2016-2089.patch")
-                  (search-patch "jasper-CVE-2016-2116.patch")))))
+              (patches (search-patches
+                        "jasper-CVE-2007-2721.patch"
+                        "jasper-CVE-2008-3520.patch"
+                        "jasper-CVE-2008-3522.patch"
+                        "jasper-CVE-2011-4516-and-CVE-2011-4517.patch"
+                        "jasper-CVE-2014-8137.patch"
+                        "jasper-CVE-2014-8138.patch"
+                        "jasper-CVE-2014-8157.patch"
+                        "jasper-CVE-2014-8158.patch"
+                        "jasper-CVE-2014-9029.patch"
+                        "jasper-CVE-2016-1577.patch"
+                        "jasper-CVE-2016-1867.patch"
+                        "jasper-CVE-2016-2089.patch"
+                        "jasper-CVE-2016-2116.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("unzip" ,unzip)))
diff --git a/gnu/packages/imagemagick.scm b/gnu/packages/imagemagick.scm
index a68e9aa159..2bdc333d91 100644
--- a/gnu/packages/imagemagick.scm
+++ b/gnu/packages/imagemagick.scm
@@ -48,7 +48,7 @@
              (sha256
               (base32
                "159afhqrj22jlz745ccbgnkdiwvn8pjcc96jic0iv9ms7gqxwln5"))
-             (patches (list (search-patch "imagemagick-test-segv.patch")))))
+             (patches (search-patches "imagemagick-test-segv.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags '("--with-frozenpaths")
diff --git a/gnu/packages/irc.scm b/gnu/packages/irc.scm
index a17330ec63..64edf652f8 100644
--- a/gnu/packages/irc.scm
+++ b/gnu/packages/irc.scm
@@ -52,7 +52,7 @@
 (define-public quassel
   (package
     (name "quassel")
-    (version "0.12.3")
+    (version "0.12.4")
     (source
       (origin
         (method url-fetch)
@@ -60,7 +60,7 @@
                             version ".tar.bz2"))
         (sha256
          (base32
-          "0d6lwf6qblj1ia5j9mjy112zrmpbbg9mmxgscbgxiqychldyjgjd"))))
+          "0ka456fb8ha3w7g74xlzfg6w4azxjjxgrhl4aqpbwg3lnd6fbr4k"))))
     (build-system cmake-build-system)
     (arguments
       ;; The three binaries are not mutually exlusive, and are all built
@@ -142,7 +142,7 @@ SILC and ICB protocols via plugins.")
               (sha256
                (base32
                 "19apd3hav77v74j7flicai0843k7wrkr2fd3q2ayvzkgnbrrp1ai"))
-              (patches (list (search-patch "weechat-python.patch")))))
+              (patches (search-patches "weechat-python.patch"))))
     (build-system gnu-build-system)
     (native-inputs `(("autoconf" ,autoconf)
                      ("pkg-config" ,pkg-config)
diff --git a/gnu/packages/java.scm b/gnu/packages/java.scm
index 9b6a647f25..c94f2e4b28 100644
--- a/gnu/packages/java.scm
+++ b/gnu/packages/java.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
+;;; Copyright © 2016 Roel Janssen <roel@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,6 +23,7 @@
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix utils)
+  #:use-module (guix build-system ant)
   #:use-module (guix build-system gnu)
   #:use-module (gnu packages)
   #:use-module (gnu packages attr)
@@ -51,19 +53,19 @@
   #:use-module (gnu packages texinfo)
   #:use-module ((srfi srfi-1) #:select (fold alist-delete)))
 
-(define-public swt
+(define-public java-swt
   (package
-    (name "swt")
-    (version "4.4.2")
+    (name "java-swt")
+    (version "4.5")
     (source (origin
               (method url-fetch)
               (uri (string-append
                     "http://ftp-stud.fht-esslingen.de/pub/Mirrors/"
                     "eclipse/eclipse/downloads/drops4/R-" version
-                    "-201502041700/swt-" version "-gtk-linux-x86.zip"))
+                    "-201506032000/swt-" version "-gtk-linux-x86.zip"))
               (sha256
                (base32
-                "0lzyqr8k2zm5s8fmnrx5kxpslxfs0i73y26fwfms483x45izzwj8"))))
+                "03mhzraikcs4fsz7d3h5af9pw1bbcfd6dglsvbk2ciwimy9zj30q"))))
     (build-system gnu-build-system)
     (arguments
      `(#:make-flags '("-f" "make_linux.mak")
@@ -577,7 +579,7 @@ build process and its dependencies, whereas Make uses Makefile format.")
     (license license:gpl2+)))
 
 (define-public icedtea-7
-  (let* ((version "2.6.4")
+  (let* ((version "2.6.6")
          (drop (lambda (name hash)
                  (origin
                    (method url-fetch)
@@ -594,7 +596,7 @@ build process and its dependencies, whereas Make uses Makefile format.")
                       version ".tar.xz"))
                 (sha256
                  (base32
-                  "0r31h8nlsrbfdkgbjbb7phwgcwglc9siznzrr40lqnm9xrgkc2nj"))
+                  "0jjldnig382yqvzzsflilcz897v2lwnw4n57sggdjn318d29g53r"))
                 (modules '((guix build utils)))
                 (snippet
                  '(substitute* "Makefile.in"
@@ -669,6 +671,8 @@ build process and its dependencies, whereas Make uses Makefile format.")
                       (setenv "CC" "gcc")
                       (setenv "CPATH"
                               (string-append gcjinclude ":"
+                                             (assoc-ref inputs "libxcomposite")
+                                             "/include/X11/extensions" ":"
                                              (assoc-ref inputs "libxrender")
                                              "/include/X11/extensions" ":"
                                              (assoc-ref inputs "libxtst")
@@ -719,26 +723,139 @@ build process and its dependencies, whereas Make uses Makefile format.")
       (native-inputs
        `(("openjdk-src"
           ,(drop "openjdk"
-                 "1qjjf71nq80ac2d08hbaa8589d31vk313z3rkirnwq5df8cyf0mv"))
+                 "1wxd5kbsmd4gdiz78iq7pq9hp0l6m946pd1pvaj750lkrgk17y14"))
          ("corba-drop"
           ,(drop "corba"
-                 "025warxhjal3nr7w1xyd16k0f32fwkchifpaslzyidsga3hgmfr6"))
+                 "0bba7drdpbggzgn7cnqv10myxa3bygaq2hkclgrmsijhl6bnr26f"))
          ("jaxp-drop"
           ,(drop "jaxp"
-                 "0qiz6swb78w9c0mf88pf0gflgm5rp9k0l6fv6sdl7dki691b0z09"))
+                 "0c1d4yjaxzh9fi9bx50yi2psb9f475bfivivf6c31smgaihb97k7"))
          ("jaxws-drop"
           ,(drop "jaxws"
-                 "18fz4gl4fdlcmqvh1mlpd9h0gj0qizpfa7njkax97aysmsm08xns"))
+                 "0662wzws45jwzwfc4pgizxdywz737vflkj9w3hw1xlgljs017bzr"))
          ("jdk-drop"
           ,(drop "jdk"
-                 "0qsx5d9pgwlz9vbpapw4jwpajqc6rwk1150cjb33i4n3z709jccx"))
+                 "17qaf5mdijsn6jzyxv7rgn9g5mazkva6p8lcy7zq06yvfb595ahv"))
          ("langtools-drop"
           ,(drop "langtools"
-                 "1k6plx96smf86z303gb30hncssa8f40qdryzsdv349iwqwacxc7r"))
+                 "1wv34cyba1f4wynjkwf765agf4ifc04717ac7b3bpiagggp2rfsl"))
          ("hotspot-drop"
           ,(drop "hotspot"
-                 "0r9ffzyf5vxs8wg732szqcil0ksc8lcxzihdv3viz7d67dy42irp"))
+                 "1hhd5q2g7mnw3pqqv72labki5zv09vgc3hp3xig4x8r4yzzg9s54"))
          ,@(fold alist-delete (package-native-inputs icedtea-6)
-                 '("openjdk6-src")))))))
+                 '("openjdk6-src"))))
+      (inputs
+       `(("libxcomposite" ,libxcomposite)
+         ,@(package-inputs icedtea-6))))))
+
+(define-public icedtea-8
+  (let* ((version "3.0.1")
+         (drop (lambda (name hash)
+                 (origin
+                   (method url-fetch)
+                   (uri (string-append
+                         "http://icedtea.classpath.org/download/drops/"
+                         "/icedtea8/" version "/" name ".tar.xz"))
+                   (sha256 (base32 hash))))))
+    (package (inherit icedtea-7)
+      (version "3.0.1")
+      (source (origin
+                (method url-fetch)
+                (uri (string-append
+                      "http://icedtea.wildebeest.org/download/source/icedtea-"
+                      version ".tar.xz"))
+                (sha256
+                 (base32
+                  "1wislw090zx955rf9sppimdzqf044mpj96xp54vljv6yw46y6v1l"))
+                (modules '((guix build utils)))
+                (snippet
+                 '(substitute* "Makefile.am"
+                    ;; do not leak information about the build host
+                    (("DISTRIBUTION_ID=\"\\$\\(DIST_ID\\)\"")
+                     "DISTRIBUTION_ID=\"\\\"guix\\\"\"")))))
+      (arguments
+       (substitute-keyword-arguments (package-arguments icedtea-7)
+         ((#:configure-flags flags)
+          `(let ((jdk (assoc-ref %build-inputs "jdk")))
+             `(;;"--disable-bootstrap"
+               "--enable-bootstrap"
+               "--enable-nss"
+               "--disable-downloading"
+               "--disable-tests"      ;they are run in the check phase instead
+               "--with-openjdk-src-dir=./openjdk.src"
+               ,(string-append "--with-jdk-home=" jdk))))
+         ((#:phases phases)
+          `(modify-phases ,phases
+             (delete 'fix-x11-extension-include-path)
+             (delete 'patch-paths)
+             (delete 'set-additional-paths)
+             (delete 'patch-patches)
+             (replace 'install
+               (lambda* (#:key outputs #:allow-other-keys)
+                 (let ((doc (string-append (assoc-ref outputs "doc")
+                                           "/share/doc/icedtea"))
+                       (jre (assoc-ref outputs "out"))
+                       (jdk (assoc-ref outputs "jdk")))
+                   (copy-recursively "openjdk.build/docs" doc)
+                   (copy-recursively "openjdk.build/images/j2re-image" jre)
+                   (copy-recursively "openjdk.build/images/j2sdk-image" jdk)
+                   #t)))))))
+      (native-inputs
+       `(("jdk" ,icedtea-7 "jdk")
+         ("openjdk-src"
+          ,(drop "openjdk"
+                 "1141wfz6vz889f5naj7zdbyw42ibw0ixvkd808lfcrwxlgznyxlb"))
+         ("corba-drop"
+          ,(drop "corba"
+                 "0l3fmfw88hf8709z033az1x6wzmcb0jnakj2br1r721zw01i0da2"))
+         ("jaxp-drop"
+          ,(drop "jaxp"
+                 "1i1pvyrdkk3w8vcnk6kfcbsjkfpbbrcywiypdl39bf2ishixbaf0"))
+         ("jaxws-drop"
+          ,(drop "jaxws"
+                 "0f1kglci65zsfy8ygw5w2zza7v1280znihvls4kraz06dgsc2y73"))
+         ("jdk-drop"
+          ,(drop "jdk"
+                 "1pcwb1kjd1ph4jbv07icgk0fb8jqnck2y24qjfd7dzg7gm45c1am"))
+         ("langtools-drop"
+          ,(drop "langtools"
+                 "1jjil9s244wp0blj1qkzk7sy7y1jrxb4wq18c1rj2q2pa88n00i6"))
+         ("hotspot-drop"
+          ,(drop "hotspot"
+                 "1pl0cz1gja6z5zbywni1x1pj4qkh745fpj55fcmj4lpfj2p98my1"))
+         ("nashorn-drop"
+          ,(drop "nashorn"
+                 "1p0ynm2caraq1sal38qrrf42yah7j14c9vfwdv6h5h4rliahs177"))
+         ,@(fold alist-delete (package-native-inputs icedtea-7)
+                 '("gcj" "openjdk-src" "corba-drop" "jaxp-drop" "jaxws-drop"
+                   "jdk-drop" "langtools-drop" "hotspot-drop")))))))
 
 (define-public icedtea icedtea-7)
+
+(define-public java-xz
+  (package
+   (name "java-xz")
+   (version "1.5")
+   (source (origin
+     (method url-fetch)
+     (uri (string-append "http://tukaani.org/xz/xz-java-" version ".zip"))
+     (sha256
+      (base32
+       "0x6vn9dp9kxk83x2fp3394n95dk8fx9yg8jns9371iqsn0vy8ih1"))))
+   (build-system ant-build-system)
+   (arguments
+    `(#:tests? #f ; There are no tests to run.
+      #:jar-name ,(string-append "xz-" version  ".jar")
+      #:phases
+      (modify-phases %standard-phases
+        ;; The unpack phase enters the "maven" directory by accident.
+        (add-after 'unpack 'chdir
+          (lambda _ (chdir "..") #t)))))
+   (native-inputs
+    `(("unzip" ,unzip)))
+   (home-page "http://tukaani.org/xz/java.html")
+   (synopsis "Implementation of XZ data compression in pure Java")
+   (description "This library aims to be a complete implementation of XZ data
+compression in pure Java.  Single-threaded streamed compression and
+decompression and random access decompression have been fully implemented.")
+   (license license:public-domain)))
diff --git a/gnu/packages/kde-frameworks.scm b/gnu/packages/kde-frameworks.scm
index 2f49dc098a..0b747def14 100644
--- a/gnu/packages/kde-frameworks.scm
+++ b/gnu/packages/kde-frameworks.scm
@@ -27,7 +27,7 @@
   #:use-module (gnu packages qt)
   #:use-module (gnu packages xorg))
 
-(define kde-frameworks-version "5.19.0")
+(define kde-frameworks-version "5.21.0")
 
 (define-public extra-cmake-modules
   (package
@@ -41,7 +41,7 @@
                             name "-" version ".tar.xz"))
         (sha256
          (base32
-          "1dl3hhbara7iswb5wsc5dp17ar3ljw5f0nrncl8vry9smaz2zl63"))))
+          "1kbc5fkcbz9vkg0jpz10vsfgwajlrsmbl0vrbls5qvrdgbgrwlm3"))))
     ;; The package looks for Qt5LinguistTools provided by Qt, but apparently
     ;; compiles without it; it might be needed for building the
     ;; documentation, which requires the additional Sphinx package.
@@ -66,7 +66,7 @@ common build settings used in software produced by the KDE community.")
                             name "-" version ".tar.xz"))
         (sha256
          (base32
-          "115xs34r74j9zcsw69glnh8w59iyh764n3gniawwrk23c6yb8fch"))))
+          "13lfwpw5a4in0mp5y8d15jg6xhhrka2qmw73wrdzcvj22n6ldzzi"))))
     (build-system cmake-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
@@ -104,7 +104,7 @@ lower level classes for interaction with the X Windowing System.")
                             name "5-"version ".tar.xz"))
         (sha256
          (base32
-          "09vfwcyidj3bl0qr4sq78bkc69zp9x8dwp8bsay5y05q8591dkg0"))))
+          "00qh1h3xx392hh73zdlknc1j9i2sck9ys74a9ffkf6an4rl0hws5"))))
     (build-system cmake-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
diff --git a/gnu/packages/ldc.scm b/gnu/packages/ldc.scm
index 66da63581c..1709f59f4c 100644
--- a/gnu/packages/ldc.scm
+++ b/gnu/packages/ldc.scm
@@ -129,7 +129,7 @@ and freshness without requiring additional information from the user.")
            (sha256
             (base32
              "0sgdj0536c4nb118yiw1f8lqy5d3g3lpg9l99l165lk9xy45l9z4"))
-           (patches (list (search-patch "ldc-disable-tests.patch")))))
+           (patches (search-patches "ldc-disable-tests.patch"))))
        ("druntime-src"
         ,(origin
            (method url-fetch)
diff --git a/gnu/packages/libcanberra.scm b/gnu/packages/libcanberra.scm
index bfa7715160..6bac0bcd5b 100644
--- a/gnu/packages/libcanberra.scm
+++ b/gnu/packages/libcanberra.scm
@@ -64,7 +64,7 @@
       ;; his pleasure.
       (patch-flags '("-p0"))
       (patches
-       (list (search-patch "libcanberra-sound-theme-freedesktop.patch")))))
+       (search-patches "libcanberra-sound-theme-freedesktop.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("alsa-lib" ,alsa-lib)
diff --git a/gnu/packages/libevent.scm b/gnu/packages/libevent.scm
index b4c9c0ce5e..c9e57d6331 100644
--- a/gnu/packages/libevent.scm
+++ b/gnu/packages/libevent.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Eric Dvorsak <eric@dvorsak.fr>
+;;; Copyright © 2016 David Thompson <davet@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -41,7 +42,7 @@
              (sha256
               (base32
                "18qz9qfwrkakmazdlwxvjmw8p76g70n3faikwvdwznns1agw9hki"))
-             (patches (list (search-patch "libevent-dns-tests.patch")))))
+             (patches (search-patches "libevent-dns-tests.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(;; Dependencies used for the tests and for `event_rpcgen.py'.
@@ -88,7 +89,7 @@ programs.")
 (define-public libuv
   (package
     (name "libuv")
-    (version "1.4.2")
+    (version "1.9.0")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://github.com/libuv/libuv/archive/v"
@@ -96,7 +97,7 @@ programs.")
               (file-name (string-append name "-" version ".tar.gz"))
               (sha256
                (base32
-                "0hdpysawz85zpmsfkcsd1b7bmx53szcir1szbh1w7ldhkpv29r5r"))))
+                "1sx5lahhg2w92y6mgyg7c7nrx2biyyxd5yiqkmq8n4w01lm2gf7q"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-cons-after
diff --git a/gnu/packages/libreoffice.scm b/gnu/packages/libreoffice.scm
index 9d58a267b6..5256c49035 100644
--- a/gnu/packages/libreoffice.scm
+++ b/gnu/packages/libreoffice.scm
@@ -250,7 +250,7 @@ working with graphics in the WPG (WordPerfect Graphics) format.")
                           version ".tar.gz"))
       (sha256 (base32
                "1dprvk4fibylv24l7gr49gfqbkfgmxynvgssvdcycgpf7n8h4zm8"))
-      (patches (list (search-patch "libcmis-fix-test-onedrive.patch")))))
+      (patches (search-patches "libcmis-fix-test-onedrive.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("cppunit" ,cppunit)
diff --git a/gnu/packages/libunwind.scm b/gnu/packages/libunwind.scm
index ab3496277a..cda83b2bc0 100644
--- a/gnu/packages/libunwind.scm
+++ b/gnu/packages/libunwind.scm
@@ -35,7 +35,7 @@
              (sha256
               (base32
                "16nhx2pahh9d62mvszc88q226q5lwjankij276fxwrm8wb50zzlx"))
-             (patches (list (search-patch "libunwind-CVE-2015-3239.patch")))))
+             (patches (search-patches "libunwind-CVE-2015-3239.patch"))))
     (build-system gnu-build-system)
     (arguments
      ;; FIXME: As of glibc 2.17, we get 3 out of 34 test failures.
diff --git a/gnu/packages/libusb.scm b/gnu/packages/libusb.scm
index c3427e7f6f..1e72442c73 100644
--- a/gnu/packages/libusb.scm
+++ b/gnu/packages/libusb.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2012 Nikita Karetnikov <nikita@karetnikov.org>
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015 Andy Wingo <wingo@igalia.com>
-;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -28,11 +28,13 @@
   #:use-module (guix download)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system glib-or-gtk)
+  #:use-module (guix build-system python)
   #:use-module (gnu packages gnupg)
   #:use-module (gnu packages gtk)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages mp3)
   #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages python)
   #:use-module (gnu packages xiph))
 
 (define-public libusb
@@ -87,6 +89,49 @@ devices on various operating systems.")
 version of libusb to run with newer libusb.")
     (license lgpl2.1+)))
 
+(define-public python-pyusb
+  (package
+    (name "python-pyusb")
+    (version "1.0.0rc1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "pyusb" version))
+       (sha256
+        (base32
+         "07cjq11qhngzjd746k7688s6y2x7lpj669fxqfsiy985rg0jsn7j"))))
+    (build-system python-build-system)
+    (arguments
+     `(#:tests? #f  ;no tests
+       #:modules ((srfi srfi-26)
+                  (guix build utils)
+                  (guix build python-build-system))
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'fix-libusb-reference
+           (lambda* (#:key inputs #:allow-other-keys)
+             (substitute* "usb/libloader.py"
+               (("lib = locate_library\\(candidates, find_library\\)")
+                (string-append
+                 "lib = \""
+                 (car (find-files (assoc-ref inputs "libusb")
+                                  (lambda (file stat)
+                                    (and ((file-name-predicate
+                                           "^libusb-.*\\.so\\..*") file stat)
+                                         (not (symbolic-link? file))))))
+                 "\"")))
+             #t)))))
+    (inputs
+     `(("libusb" ,libusb)))
+    (home-page "http://walac.github.io/pyusb/")
+    (synopsis "Python bindings to the libusb library")
+    (description
+     "PyUSB aims to be an easy to use Python module to access USB devices.")
+    (license bsd-3)))
+
+(define-public python2-pyusb
+  (package-with-python2 python-pyusb))
+
 (define-public libmtp
   (package
     (name "libmtp")
@@ -98,7 +143,7 @@ version of libusb to run with newer libusb.")
              (sha256
                (base32
                 "12dinqic0ljnhrwx3rc61jc7q24ybr0mckc2ya5kh1s1np0d7w93"))
-             (patches (list (search-patch "libmtp-devices.patch")))))
+             (patches (search-patches "libmtp-devices.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 59258af15f..5f4b041694 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -10,6 +10,7 @@
 ;;; Copyright © 2016 Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>
 ;;; Copyright © 2016 Alex Kost <alezost@gmail.com>
 ;;; Copyright © 2016 Raymond Nicholson <rain1@openmailbox.org>
+;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -81,6 +82,7 @@
     (cond ((string=? arch "i686") "i386")
           ((string-prefix? "mips" arch) "mips")
           ((string-prefix? "arm" arch) "arm")
+          ((string-prefix? "aarch64" arch) "arm64")
           (else arch))))
 
 (define (linux-libre-urls version)
@@ -170,8 +172,7 @@
              (sha256
               (base32
                "0jxnz9ahfic79rp93l5wxcbgh4pkv85mwnjlbv1gz3jawv5cvwp1"))
-             (patches
-              (list (search-patch "module-init-tools-moduledir.patch")))))
+             (patches (search-patches "module-init-tools-moduledir.patch"))))
     (build-system gnu-build-system)
     (arguments
      ;; FIXME: The upstream tarball lacks man pages, and building them would
@@ -221,7 +222,7 @@ for SYSTEM and optionally VARIANT, or #f if there is no such configuration."
     (search-path %load-path file)))
 
 (define-public linux-libre
-  (let* ((version "4.5")
+  (let* ((version "4.5.2")
          (build-phase
           '(lambda* (#:key system inputs #:allow-other-keys #:rest args)
              ;; Avoid introducing timestamps
@@ -299,7 +300,7 @@ for SYSTEM and optionally VARIANT, or #f if there is no such configuration."
              (uri (linux-libre-urls version))
              (sha256
               (base32
-               "0km863vwy557flpygkr869yshpjs1v11ni78p8k9p9nm31ai6yn3"))))
+               "0mw8n5pms33k3m3aamlryahrcbhfnqbzvkglgw3j4dhaja3hwr7n"))))
     (build-system gnu-build-system)
     (supported-systems '("x86_64-linux" "i686-linux"))
     (native-inputs `(("perl" ,perl)
@@ -336,13 +337,13 @@ It has been modified to remove all non-free binary blobs.")
 (define-public linux-libre-4.4
   (package
     (inherit linux-libre)
-    (version "4.4.6")
+    (version "4.4.8")
     (source (origin
               (method url-fetch)
               (uri (linux-libre-urls version))
               (sha256
                (base32
-                "0sf623knc4j23p96r0w1ng725kj45ra50bwix01z5nvl5aqpnsrp"))))
+                "0zyhdy01gjglgmlrmpqa1sdnm0z91mzwspbksj6zvcamczb8ml53"))))
     (native-inputs
      (let ((conf (kernel-config (or (%current-target-system)
                                     (%current-system))
@@ -353,13 +354,13 @@ It has been modified to remove all non-free binary blobs.")
 (define-public linux-libre-4.1
   (package
     (inherit linux-libre)
-    (version "4.1.20")
+    (version "4.1.22")
     (source (origin
               (method url-fetch)
               (uri (linux-libre-urls version))
               (sha256
                (base32
-                "0vwk6jh57djbwr29xvlgaf14409bq9vmwf6r6nq9jdl6dizfd110"))))
+                "0bn6qba7q4i3yn3zx2p56gawnb2gczrf4vyrjggirj4d60gvng7y"))))
     (native-inputs
      (let ((conf (kernel-config (or (%current-target-system)
                                     (%current-system))
@@ -453,7 +454,7 @@ providing the system administrator with some help in common tasks.")
               (sha256
                (base32
                 "1ivdx1bhjbakf77agm9dn3wyxia1wgz9lzxgd61zqxw3xzih9gzw"))
-              (patches (list (search-patch "util-linux-tests.patch")))
+              (patches (search-patches "util-linux-tests.patch"))
               (modules '((guix build utils)))
               (snippet
                ;; We take the 'logger' program from GNU Inetutils and 'kill'
@@ -610,7 +611,7 @@ slabtop, and skill.")
     (native-inputs `(("pkg-config" ,pkg-config)
                      ("texinfo" ,texinfo)))     ;for the libext2fs Info manual
     (arguments
-     '(;; util-linux is not the preferred source for some of the libraries and
+     '(;; util-linux is the preferred source for some of the libraries and
        ;; commands, so disable them (see, e.g.,
        ;; <http://git.buildroot.net/buildroot/commit/?id=e1ffc2f791b33633>.)
        #:configure-flags '("--disable-libblkid"
@@ -820,7 +821,7 @@ intercept and print the system calls executed by the program.")
              (sha256
               (base32
                "0fx057746dj7rjdi0jnvx2m9b0y1lgdkh1hks87d8w32xyihf3k9"))
-             (patches (list (search-patch "alsa-lib-mips-atomic-fix.patch")))))
+             (patches (search-patches "alsa-lib-mips-atomic-fix.patch"))))
     (build-system gnu-build-system)
     (home-page "http://www.alsa-project.org/")
     (synopsis "The Advanced Linux Sound Architecture libraries")
@@ -981,8 +982,7 @@ manpages.")
              (sha256
               (base32
                "0yvxrzk0mzmspr7sa34hm1anw6sif39gyn85w4c5ywfn8inxvr3s"))
-             (patches
-              (list (search-patch "net-tools-bitrot.patch")))))
+             (patches (search-patches "net-tools-bitrot.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:modules ((guix build gnu-build-system)
@@ -1477,14 +1477,14 @@ system.")
 (define-public kbd
   (package
     (name "kbd")
-    (version "2.0.2")
+    (version "2.0.3")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://kernel.org/linux/utils/kbd/kbd-"
                                   version ".tar.xz"))
               (sha256
                (base32
-                "04mrms12nm5sas0nxs94yrr3hz7gmqhnmfgb9ff34bh1jszxmzcx"))
+                "0ppv953gn2zylcagr4z6zg5y2x93dxrml29plypg6xgbq3hrv2bs"))
               (modules '((guix build utils)))
               (snippet
                '(begin
@@ -1498,27 +1498,26 @@ system.")
                      "tty"))))))
     (build-system gnu-build-system)
     (arguments
-     '(#:phases (alist-cons-before
-                 'build 'pre-build
-                 (lambda* (#:key inputs #:allow-other-keys)
-                   (let ((gzip  (assoc-ref %build-inputs "gzip"))
-                         (bzip2 (assoc-ref %build-inputs "bzip2")))
-                     (substitute* "src/libkeymap/findfile.c"
-                       (("gzip")
-                        (string-append gzip "/bin/gzip"))
-                       (("bzip2")
-                        (string-append bzip2 "/bin/bzip2")))))
-                 (alist-cons-after
-                  'install 'post-install
-                  (lambda* (#:key outputs #:allow-other-keys)
-                    ;; Make sure these programs find their comrades.
-                    (let* ((out (assoc-ref outputs "out"))
-                           (bin (string-append out "/bin")))
-                      (for-each (lambda (prog)
-                                  (wrap-program (string-append bin "/" prog)
-                                                `("PATH" ":" prefix (,bin))))
-                                '("unicode_start" "unicode_stop"))))
-                  %standard-phases))))
+     '(#:phases
+       (modify-phases %standard-phases
+         (add-before 'build 'pre-build
+           (lambda* (#:key inputs #:allow-other-keys)
+             (let ((gzip  (assoc-ref %build-inputs "gzip"))
+                   (bzip2 (assoc-ref %build-inputs "bzip2")))
+               (substitute* "src/libkeymap/findfile.c"
+                 (("gzip")
+                  (string-append gzip "/bin/gzip"))
+                 (("bzip2")
+                  (string-append bzip2 "/bin/bzip2"))))))
+         (add-after 'install 'post-install
+           (lambda* (#:key outputs #:allow-other-keys)
+             ;; Make sure these programs find their comrades.
+             (let* ((out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin")))
+               (for-each (lambda (prog)
+                           (wrap-program (string-append bin "/" prog)
+                             `("PATH" ":" prefix (,bin))))
+                         '("unicode_start" "unicode_stop"))))))))
     (inputs `(("check" ,check)
               ("gzip" ,gzip)
               ("bzip2" ,bzip2)
@@ -1564,7 +1563,7 @@ to use Linux' inotify mechanism, which allows file accesses to be monitored.")
               (sha256
                (base32
                 "1yid3a9b64a60ybj66fk2ysrq5klnl0ijl4g624cl16y8404g9rv"))
-              (patches (list (search-patch "kmod-module-directory.patch")))))
+              (patches (search-patches "kmod-module-directory.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
@@ -1609,7 +1608,7 @@ from the module-init-tools project.")
               (sha256
                (base32
                 "0akg9gcc3c2p56xbhlvbybqavcprly5q0bvk655zwl6d62j8an7p"))
-              (patches (list (search-patch "eudev-rules-directory.patch")))))
+              (patches (search-patches "eudev-rules-directory.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
@@ -1743,7 +1742,7 @@ interface.")
               (sha256
                (base32
                 "1gydiqgb08d9gbx4l6gv98zg3pljc984m50hmn3ysxcbkxkvkz23"))
-              (patches (list (search-patch "crda-optional-gcrypt.patch")))))
+              (patches (search-patches "crda-optional-gcrypt.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (modify-phases %standard-phases
@@ -1861,7 +1860,7 @@ country-specific regulations for the wireless spectrum.")
               (sha256
                (base32
                 "1ksgrynxgrq590nb2fwxrl1gwzisjkqlyg3ljfd1al0ibrk6mbjx"))
-              (patches (list (search-patch "lm-sensors-hwmon-attrs.patch")))))
+              (patches (search-patches "lm-sensors-hwmon-attrs.patch"))))
     (build-system gnu-build-system)
     (inputs `(("rrdtool" ,rrdtool)
               ("perl" ,perl)
@@ -2118,6 +2117,26 @@ WLAN, Bluetooth and mobile broadband.")
     (license (license:non-copyleft "file://COPYING"
                                    "See COPYING in the distribution."))))
 
+(define-public acpi
+  (package
+    (name "acpi")
+    (version "1.7")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://sourceforge/acpiclient/"
+                                  name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "01ahldvf0gc29dmbd5zi4rrnrw2i1ajnf30sx2vyaski3jv099fp"))))
+    (build-system gnu-build-system)
+    (home-page "http://acpiclient.sourceforge.net")
+    (synopsis "Display information on ACPI devices")
+    (description "@code{acpi} attempts to replicate the functionality of the
+\"old\" @code{apm} command on ACPI systems, including battery and thermal
+information.  It does not support ACPI suspending, only displays information
+about ACPI devices.")
+    (license license:gpl2+)))
+
 (define-public acpid
   (package
     (name "acpid")
@@ -2201,7 +2220,7 @@ also contains the libsysfs library.")
          version ".tar.gz"))
        (sha256
         (base32 "0qfqv7nqmjfr3p0bwrdlxkiqwqr7vmx053cadaa548ybqbghxmvm"))
-       (patches (list (search-patch "cpufrequtils-fix-aclocal.patch")))))
+       (patches (search-patches "cpufrequtils-fix-aclocal.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("sysfsutils" ,sysfsutils-1)))
@@ -2298,7 +2317,7 @@ MPEG-2 and audio over Linux IEEE 1394.")
               (sha256
                (base32
                 "132vdvh3myjgcjn6i9w90ck16ddjxjcszklzkyvr4f5ifqd7wfhg"))
-              (patches (list (search-patch "mdadm-gcc-4.9-fix.patch")))))
+              (patches (search-patches "mdadm-gcc-4.9-fix.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("udev" ,eudev)))
@@ -2499,7 +2518,7 @@ and copy/paste text in the console and in xterm.")
 (define-public btrfs-progs
   (package
     (name "btrfs-progs")
-    (version "4.4.1")
+    (version "4.5.1")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://kernel.org/linux/kernel/"
@@ -2507,7 +2526,7 @@ and copy/paste text in the console and in xterm.")
                                   "btrfs-progs-v" version ".tar.xz"))
               (sha256
                (base32
-                "1z5882zx9jx02vyg067siws0irsl8pg37myx17hr4imn9ypf6r4r"))))
+                "1znf2zhb56zbmdjk3lq107678xwsqwc5gczspypmc5i31qnppy7f"))))
     (build-system gnu-build-system)
     (outputs '("out"
                "static"))      ; static versions of binaries in "out" (~16MiB!)
diff --git a/gnu/packages/lirc.scm b/gnu/packages/lirc.scm
index f8828d3f03..b077825529 100644
--- a/gnu/packages/lirc.scm
+++ b/gnu/packages/lirc.scm
@@ -39,7 +39,7 @@
               (sha256
                (base32
                 "19c6ldjsdnk1md66q3nb035ja1xj217k8iabhxpsb8rs10a6kwi6"))
-              (patches (list (search-patch "lirc-localstatedir.patch")))))
+              (patches (search-patches "lirc-localstatedir.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags '("--localstatedir=/var")))
diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index d5e5ed65ad..3bf019fa83 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -102,7 +102,7 @@ compiler.  In LLVM this library is called \"compiler-rt\".")
        (uri (string-append "http://llvm.org/releases/"
                            version "/cfe-" version ".src.tar.xz"))
        (sha256 (base32 hash))
-       (patches (list (search-patch "clang-libc-search-path.patch")))))
+       (patches (search-patches "clang-libc-search-path.patch"))))
     ;; Using cmake allows us to treat llvm as an external library.  There
     ;; doesn't seem to be any way to do this with clang's autotools-based
     ;; build system.
diff --git a/gnu/packages/lsh.scm b/gnu/packages/lsh.scm
index 3b6487f38c..bb941365a9 100644
--- a/gnu/packages/lsh.scm
+++ b/gnu/packages/lsh.scm
@@ -44,7 +44,7 @@
       (sha256
        (base32
         "0z6rlalhvfca64jpvksppc9bdhs7jwhiw4y35g5ibvh91xp3rn1l"))
-      (patches (list (search-patch "liboop-mips64-deplibs-fix.patch")))))
+      (patches (search-patches "liboop-mips64-deplibs-fix.patch"))))
     (build-system gnu-build-system)
     (home-page "http://www.lysator.liu.se/liboop/")
     (synopsis "Event loop library")
diff --git a/gnu/packages/lua.scm b/gnu/packages/lua.scm
index fcb41831eb..17874f86ab 100644
--- a/gnu/packages/lua.scm
+++ b/gnu/packages/lua.scm
@@ -37,8 +37,8 @@
                                  version ".tar.gz"))
              (sha256
               (base32 "0b8034v1s82n4dg5rzcn12067ha3nxaylp2vdp8gg08kjsbzphhk"))
-             (patches (list (search-patch "lua-pkgconfig.patch")
-                            (search-patch "lua52-liblua-so.patch")))))
+             (patches (search-patches "lua-pkgconfig.patch"
+                                      "lua52-liblua-so.patch"))))
     (build-system gnu-build-system)
     (inputs `(("readline" ,readline)))
     (arguments
@@ -78,7 +78,7 @@ for configuration, scripting, and rapid prototyping.")
                                  version ".tar.gz"))
              (sha256
               (base32 "0cskd4w0g6rdm2q8q3i4n1h3j8kylhs3rq8mxwl9vwlmlxbgqh16"))
-             (patches (list (search-patch "lua51-liblua-so.patch")))))))
+             (patches (search-patches "lua51-liblua-so.patch"))))))
 
 (define-public luajit
   (package
@@ -90,8 +90,8 @@ for configuration, scripting, and rapid prototyping.")
                                   version ".tar.gz"))
               (sha256
                (base32 "0ydxpqkmsn2c341j4r2v6r5r0ig3kbwv3i9jran3iv81s6r6rgjm"))
-              (patches (list (search-patch "luajit-symlinks.patch")
-                             (search-patch "luajit-no_ldconfig.patch")))))
+              (patches (search-patches "luajit-symlinks.patch"
+                                       "luajit-no_ldconfig.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:tests? #f                      ;luajit is distributed without tests
diff --git a/gnu/packages/lxde.scm b/gnu/packages/lxde.scm
index fe71a17406..7ce31ad36a 100644
--- a/gnu/packages/lxde.scm
+++ b/gnu/packages/lxde.scm
@@ -32,7 +32,7 @@
 (define-public libfm
   (package
     (name "libfm")
-    (version "1.2.3")
+    (version "1.2.4")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://sourceforge/project/pcmanfm/"
@@ -40,7 +40,7 @@
                                   "%29/LibFM/" name "-" version ".tar.xz"))
               (sha256
                (base32
-                "1ygvw52262r3jp1f45m9cdpx5xgvd4rkyfszslfqvg2c99ig34n6"))))
+                "0bsh4p7h2glhxf1cc1lvbxyb4qy0y1zsnl9izf7vrldkikrgc13q"))))
     (build-system gnu-build-system)
     (inputs `(("glib" ,glib)
               ("gtk+" ,gtk+-2)))
@@ -189,7 +189,7 @@ speed up the access to freedesktop.org defined application menus.")
 (define-public pcmanfm
   (package
     (name "pcmanfm")
-    (version "1.2.3")
+    (version "1.2.4")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://sourceforge/project/" name "/"
@@ -197,7 +197,7 @@ speed up the access to freedesktop.org defined application menus.")
                                   "%29/PCManFM/" name "-" version ".tar.xz"))
               (sha256
                (base32
-                "1033rw5jd7nlzbcdpx3bik7347kyh1sg1gkla424gq9vqqpxia6g"))))
+                "04z3vd9si24yi4c8calqncdpb9b6mbj4cs4f3fs86i6j05gvpk9q"))))
     (build-system gnu-build-system)
     ;; (#:configure-flags '("--sysconfdir=/etc")) suggested in README.
     (inputs `(("gtk+"   ,gtk+-2)
diff --git a/gnu/packages/lxqt.scm b/gnu/packages/lxqt.scm
index 677b580bed..38a7aea137 100644
--- a/gnu/packages/lxqt.scm
+++ b/gnu/packages/lxqt.scm
@@ -69,7 +69,7 @@ in Qt.")
        (sha256
         (base32
          "0ljdzqavvy82qwwwnhg2bgbshl2ns0k2lcswxlx1cfc8rcdr9w5l"))
-       (patches (map search-patch '("liblxqt-include.patch")))))
+       (patches (search-patches "liblxqt-include.patch"))))
     (build-system cmake-build-system)
     (arguments
      `(#:tests? #f))
diff --git a/gnu/packages/machine-learning.scm b/gnu/packages/machine-learning.scm
index 4bc37ad86d..cbc7509416 100644
--- a/gnu/packages/machine-learning.scm
+++ b/gnu/packages/machine-learning.scm
@@ -323,3 +323,22 @@ in terms of new algorithms.")
 adaptive sparsity and the Wong algorithm for adaptively sparse gaussian
 geometric models.")
     (license license:lgpl3+)))
+
+(define-public r-nnet
+  (package
+    (name "r-nnet")
+    (version "7.3-12")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "nnet" version))
+       (sha256
+        (base32
+         "17amqnw9dpap2w8ivx53hxha2xrm0drwfnj32li0xk41hlz548r7"))))
+    (build-system r-build-system)
+    (home-page "http://www.stats.ox.ac.uk/pub/MASS4/")
+    (synopsis "Feed-forward neural networks and multinomial log-linear models")
+    (description
+     "This package provides functions for feed-forward neural networks with a
+single hidden layer, and for multinomial log-linear models.")
+    (license (list license:gpl2+ license:gpl3+))))
diff --git a/gnu/packages/mail.scm b/gnu/packages/mail.scm
index 7bcb93cbc6..56e85712db 100644
--- a/gnu/packages/mail.scm
+++ b/gnu/packages/mail.scm
@@ -92,7 +92,7 @@
              (sha256
               (base32
                "0szbqa12zqzldqyw97lxqax3ja2adis83i7brdfsxmrfw68iaf65"))
-             (patches (list (search-patch "m4-gets-undeclared.patch")))))
+             (patches (search-patches "m4-gets-undeclared.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(;; TODO: Add `--with-sql'.
@@ -185,7 +185,7 @@ aliasing facilities to work just as they would on normal mail.")
              (sha256
               (base32
                "06bc2drbgalkk68rzg7hq2v5m5qgjxff5357wg0419dpi8ivdbr9"))
-             (patches (list (search-patch "mutt-store-references.patch")))))
+             (patches (search-patches "mutt-store-references.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("cyrus-sasl" ,cyrus-sasl)
@@ -302,11 +302,21 @@ and corrections.  It is based on a Bayesian filter.")
                 "0462mal2fxvavxhwjk1a6vsnspx07yniifa687dwg46aplqznin4"))))
     (build-system python-build-system)
     (native-inputs `(("python" ,python-2)))
+    (inputs `(("python2-pysqlite" ,python2-pysqlite)))
     (arguments
      ;; The setup.py script expects python-2.
      `(#:python ,python-2
       ;; Tests require a modifiable IMAP account.
-       #:tests? #f))
+       #:tests? #f
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'install 'wrap-binary
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (bin (string-append out "/bin/offlineimap")))
+               (wrap-program bin
+                 `("PYTHONPATH" ":" prefix (,(getenv "PYTHONPATH"))))
+               #t))))))
     (home-page "http://www.offlineimap.org")
     (synopsis "Sync emails between two repositories")
     (description
@@ -1119,9 +1129,7 @@ deliver it in various ways.")
        ;; The following patch fixes an ambiguous definition of
        ;; getline() in formail.c.  The patch is provided by Debian as
        ;; patch 24.
-       (patches
-        (list
-         (search-patch "procmail-ambiguous-getline-debian.patch")))))
+       (patches (search-patches "procmail-ambiguous-getline-debian.patch"))))
     (arguments
      `(#:phases (modify-phases %standard-phases
                   (replace 'configure
@@ -1156,13 +1164,13 @@ maintained.")
 (define-public khard
   (package
     (name "khard")
-    (version "0.8.1")
+    (version "0.9.0")
     (source (origin
               (method url-fetch)
               (uri (pypi-uri name version))
               (sha256
                (base32
-                "098gs94qmnspdfn6ar8lycx7dbsz9bcff90aps0cmn47mw7llch0"))))
+                "0y83rji4f270hbb41m4jpr0z3yzvpvbsl32mpg9d38hlydw8fk1s"))))
     (build-system python-build-system)
     (arguments
       `(#:python ,python-2 ; only python-2 is supported.
diff --git a/gnu/packages/make-bootstrap.scm b/gnu/packages/make-bootstrap.scm
index b3c86dbebf..85dfaa6b6f 100644
--- a/gnu/packages/make-bootstrap.scm
+++ b/gnu/packages/make-bootstrap.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -683,8 +683,8 @@ for `sh' in $PATH, and without nscd, and with static NSS modules."
               ("binutils-tarball" ,%binutils-bootstrap-tarball)
               ("glibc-tarball" ,%glibc-bootstrap-tarball)
               ("coreutils&co-tarball" ,%bootstrap-binaries-tarball)))
-    (synopsis #f)
-    (description #f)
+    (synopsis "Tarballs containing all the bootstrap binaries")
+    (description synopsis)
     (home-page #f)
     (license gpl3+)))
 
diff --git a/gnu/packages/marst.scm b/gnu/packages/marst.scm
new file mode 100644
index 0000000000..7d4a4f364d
--- /dev/null
+++ b/gnu/packages/marst.scm
@@ -0,0 +1,43 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright 2016 John Darrington <jmd@gnu.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix 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 Guix 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 Guix.  If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages marst)
+  #:use-module (guix packages)
+  #:use-module (guix licenses)
+  #:use-module (guix download)
+  #:use-module (gnu packages compression)
+  #:use-module (guix build-system gnu))
+
+(define-public marst
+  (package
+    (name "marst")
+    (version "2.7")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append
+             "mirror://gnu/" name "/" name "-" version
+             ".tar.gz"))
+       (sha256
+        (base32 "0l6swjy8fjrqw89ghc1vvakg21jmpfkpsw92yssrzkg3rg8vkrry"))))
+    (build-system gnu-build-system)
+    (home-page "http://www.gnu.org/software/marst")
+    (synopsis "Algol to C translator")
+    (description "MARST is an Algol-to-C translator.  It automatically translates programs
+written on the algorithmic language Algol 60 to the C programming language.")
+    (license gpl3+)))
diff --git a/gnu/packages/maths.scm b/gnu/packages/maths.scm
index adebf09a32..d37897da20 100644
--- a/gnu/packages/maths.scm
+++ b/gnu/packages/maths.scm
@@ -1,15 +1,16 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015, 2016 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
-;;; Copyright © 2014 John Darrington <jmd@gnu.org>
+;;; Copyright © 2014, 2016 John Darrington <jmd@gnu.org>
 ;;; Copyright © 2014, 2015, 2016 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2014 Federico Beffa <beffa@fbengineering.ch>
 ;;; Copyright © 2014 Mathieu Lirzin <mathieu.lirzin@openmailbox.org>
-;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2015 Fabian Harfert <fhmgufs@web.de>
+;;; Copyright © 2016 Roel Janssen <roel@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -37,6 +38,7 @@
   #:use-module (guix build utils)
   #:use-module (guix build-system cmake)
   #:use-module (guix build-system gnu)
+  #:use-module (guix build-system r)
   #:use-module (gnu packages algebra)
   #:use-module (gnu packages bison)
   #:use-module (gnu packages boost)
@@ -78,6 +80,26 @@
   #:use-module (gnu packages zip)
   #:use-module (srfi srfi-1))
 
+(define-public c-graph
+  (package
+   (name "c-graph")
+   (version "2.0")
+   (source (origin
+            (method url-fetch)
+            (uri (string-append "mirror://gnu/c-graph/c-graph-" version
+                                ".tar.gz"))
+            (sha256 (base32
+                     "1hlvpzrh7hzzf533diyfiabzskddi8zx92av9hwkjw3l46z7qv01"))))
+   (build-system gnu-build-system)
+   (inputs
+     `(("fortran" ,gfortran)))
+   (synopsis "Visualize and analyze convolution operations")
+   (description
+    "GNU C-Graph demonstrates the theory of convolution underlying
+engineering systems and signal analysis.")
+   (license license:gpl3+)
+   (home-page "http://www.gnu.org/software/c-graph/")))
+
 (define-public units
   (package
    (name "units")
@@ -755,7 +777,7 @@ arising after the discretization of partial differential equations.")
        (sha256
         (base32
          "1820jfp3mbl7n85765v5mp6p0gzqpgr4d2lrnhwj4gl7cwp5ndah"))
-       (patches (list (search-patch "mumps-build-parallelism.patch")))))
+       (patches (search-patches "mumps-build-parallelism.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("fortran" ,gfortran)
@@ -911,6 +933,24 @@ sparse system of linear equations A x = b using Guassian elimination.")
     (inputs
      (alist-delete "pt-scotch" (package-inputs mumps-openmpi)))))
 
+(define-public r-pracma
+  (package
+    (name "r-pracma")
+    (version "1.8.8")
+    (source (origin
+      (method url-fetch)
+      (uri (cran-uri "pracma" version))
+      (sha256
+        (base32 "0ans9l5rrb7a38gyi4qx4258sd5r5668vyrk02yzjpg9k3h8l165"))))
+    (build-system r-build-system)
+    (home-page "http://cran.r-project.org/web/packages/pracma")
+    (synopsis "Practical numerical math functions")
+    (description "This package provides functions for numerical analysis and
+linear algebra, numerical optimization, differential equations, plus some
+special functions.  It uses Matlab function names where appropriate to simplify
+porting.")
+    (license license:gpl3+)))
+
 (define-public superlu
   (package
     (name "superlu")
@@ -1004,7 +1044,7 @@ also provides threshold-based ILU factorization preconditioners.")
                            "superlu_dist_" version ".tar.gz"))
        (sha256
         (base32 "1hnak09yxxp026blq8zhrl7685yip16svwngh1wysqxf8z48vzfj"))
-       (patches (list (search-patch "superlu-dist-scotchmetis.patch")))))
+       (patches (search-patches "superlu-dist-scotchmetis.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("tcsh" ,tcsh)))
@@ -1105,8 +1145,8 @@ implemented in ANSI C, and MPI for communications.")
                           "scotch_" version ".tar.gz"))
       (sha256
        (base32 "1ir088mvrqggyqdkx9qfynmiaffqbyih5qfl5mga2nrlm1qlsgzm"))
-      (patches (list (search-patch "scotch-test-threading.patch")
-                     (search-patch "pt-scotch-build-parallelism.patch")))))
+      (patches (search-patches "scotch-test-threading.patch"
+                               "pt-scotch-build-parallelism.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("zlib" ,zlib)
@@ -1331,7 +1371,7 @@ to BMP, JPEG or PNG image formats.")
        (sha256
         (base32
          "0x1rk659sn3cq0n5c90848ilzr1gb1wf0072fl6jhkdq00qgh2s0"))
-       (patches (list (search-patch "maxima-defsystem-mkdir.patch")))))
+       (patches (search-patches "maxima-defsystem-mkdir.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("gcl" ,gcl)
@@ -1444,14 +1484,14 @@ full text searching.")
 (define-public armadillo
   (package
     (name "armadillo")
-    (version "6.400.3")
+    (version "6.700.4")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://sourceforge/arma/armadillo-"
                                   version ".tar.gz"))
               (sha256
                (base32
-                "0bsgrmldlx77w5x26n3axj1hg6iw6csyw0dwl1flrbdwl51f9701"))))
+                "0dsdjcps5l2nhg0455rrc708inffarzj7n435vj4sm9lxwf21wg9"))))
     (build-system cmake-build-system)
     (arguments `(#:tests? #f)) ;no test target
     (inputs
@@ -1472,14 +1512,14 @@ associated functions (eg. contiguous and non-contiguous submatrix views).")
 
 (define-public armadillo-for-rcpparmadillo
   (package (inherit armadillo)
-    (version "6.200.2")
+    (version "6.700.3")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://sourceforge/arma/armadillo-"
                                   version ".tar.gz"))
               (sha256
                (base32
-                "1f69rlqhnf2wv8khyn2a8vi6gx1i72qgfy8b9b760ssk85dcl763"))))))
+                "1vnhifa7d0aij3kv5bxf6m91d99h3y2fyj48jrx7jcvwyb1q5wwq"))))))
 
 (define-public muparser
   (package
@@ -1920,7 +1960,7 @@ revised simplex and the branch-and-bound methods.")
        (sha256
         (base32
          "185jych0gdnpkjwxni7pd0dda149492zwq2457xdjg76bzj78mnp"))
-       (patches (list (search-patch "dealii-p4est-interface.patch")))
+       (patches (search-patches "dealii-p4est-interface.patch"))
        (modules '((guix build utils)))
        (snippet
         ;; Remove bundled sources: UMFPACK, TBB, muParser, and boost
diff --git a/gnu/packages/mcrypt.scm b/gnu/packages/mcrypt.scm
index 71cbfd1ff9..a683ad7ac9 100644
--- a/gnu/packages/mcrypt.scm
+++ b/gnu/packages/mcrypt.scm
@@ -90,7 +90,7 @@ XTEA, 3WAY, TWOFISH, BLOWFISH, ARCFOUR, WAKE and more.")
       (sha256
        (base32
         "1w7yiljan8gf1ibiypi6hm3r363imm3sxl1j8hapjdq3m591qljn"))
-      (patches (list (search-patch "mhash-keygen-test-segfault.patch")))))
+      (patches (search-patches "mhash-keygen-test-segfault.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("perl" ,perl)))                 ;for tests
diff --git a/gnu/packages/messaging.scm b/gnu/packages/messaging.scm
index 5dc4639bb4..fbe84f58b2 100644
--- a/gnu/packages/messaging.scm
+++ b/gnu/packages/messaging.scm
@@ -71,8 +71,7 @@
               (sha256
                (base32
                 "1x8rliydhbibmzwdbyr7pd7n87m2jmxnqkpvaalnf4154hj1hfwb"))
-              (patches
-               (list (search-patch "libotr-test-auth-fix.patch")))))
+              (patches (search-patches "libotr-test-auth-fix.patch"))))
     (build-system gnu-build-system)
     (propagated-inputs
      `(("libgcrypt" ,libgcrypt)))  ; libotr headers include gcrypt.h
@@ -138,14 +137,14 @@ identi.ca and status.net).")
 (define-public hexchat
   (package
     (name "hexchat")
-    (version "2.10.1")
+    (version "2.12.0")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://dl.hexchat.net/hexchat/hexchat-"
                                   version ".tar.xz"))
               (sha256
                (base32
-                "1ag9rmfisv0hsbk05jq4f1rnap7kwg90vgbmkr9zklkh6imfxk7z"))))
+                "17fncwza5r80z9r6j1lrh7h375hp4w6pay08zgnfc3qca6bjy1y2"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)
                      ("intltool" ,intltool)))
@@ -180,8 +179,8 @@ dictionaries.  HexChat can be extended with multiple addons.")
               (sha256
                (base32
                 "17k3g9qd9d010czk5846qxvzkmw4fihv8l6m2a2287crbxm3xhd4"))
-              (patches (list (search-patch "ngircd-no-dns-in-tests.patch")
-                             (search-patch "ngircd-handle-zombies.patch")))))
+              (patches (search-patches "ngircd-no-dns-in-tests.patch"
+                                       "ngircd-handle-zombies.patch"))))
     (build-system gnu-build-system)
     ;; Needed for the test suite.
     (native-inputs `(("procps" ,procps)
@@ -246,7 +245,7 @@ supports IPv6, SSL-protected connections as well as PAM for authentication.")
        (sha256
         (base32
          "01s0q30qrjlzj7kkz6f8lvrwsdd55a9yjh2xjjwyyxzw849j3bpj"))
-       (patches (list (search-patch "pidgin-add-search-path.patch")))))
+       (patches (search-patches "pidgin-add-search-path.patch"))))
     (build-system glib-or-gtk-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
diff --git a/gnu/packages/mit-krb5.scm b/gnu/packages/mit-krb5.scm
index 5f9868979a..565163732e 100644
--- a/gnu/packages/mit-krb5.scm
+++ b/gnu/packages/mit-krb5.scm
@@ -40,10 +40,10 @@
                (base32
                 "1gpscn78lv48dxccxq9ncyj53w9l2a15xmngjfa1wylvmn7g0jjx"))
               (patches
-               (map search-patch '("mit-krb5-init-context-null-spnego.patch"
-                                   "mit-krb5-CVE-2015-8629.patch"
-                                   "mit-krb5-CVE-2015-8630.patch"
-                                   "mit-krb5-CVE-2015-8631.patch")))))
+               (search-patches "mit-krb5-init-context-null-spnego.patch"
+                               "mit-krb5-CVE-2015-8629.patch"
+                               "mit-krb5-CVE-2015-8630.patch"
+                               "mit-krb5-CVE-2015-8631.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("bison" ,bison)
diff --git a/gnu/packages/mp3.scm b/gnu/packages/mp3.scm
index 5dec2a8b3f..fe1d13b382 100644
--- a/gnu/packages/mp3.scm
+++ b/gnu/packages/mp3.scm
@@ -55,10 +55,10 @@
             (sha256
              (base32
               "14460zhacxhswnzb36qfpd1f2wbk10qvksvm6wyq5hpvdgnw7ymv"))
-            (patches (map search-patch '("libmad-armv7-thumb-pt1.patch"
-                                         "libmad-armv7-thumb-pt2.patch"
-                                         "libmad-frame-length.patch"
-                                         "libmad-mips-newgcc.patch")))))
+            (patches (search-patches "libmad-armv7-thumb-pt1.patch"
+                                     "libmad-armv7-thumb-pt2.patch"
+                                     "libmad-frame-length.patch"
+                                     "libmad-mips-newgcc.patch"))))
    (build-system gnu-build-system)
    (arguments
     `(#:phases
@@ -367,8 +367,7 @@ use with CD-recording software).")
             (sha256
              (base32
               "1ss3c1a5hx6c99q1cryxg0jhbnbdj6ga9xyz0dzlz9qhzg5qswfs"))
-            (patches
-             (list (search-patch "ripperx-missing-file.patch")))))
+            (patches (search-patches "ripperx-missing-file.patch"))))
    (build-system gnu-build-system)
    (propagated-inputs
     `(("gs-fonts" ,gs-fonts)
@@ -423,7 +422,7 @@ format.")
               (sha256
                (base32
                 "0sf4pns0245009z6mbxpx7kqy4kwl69bc95wz9v23wgappsvxgy1"))
-              (patches (list (search-patch "mpc123-initialize-ao.patch")))))
+              (patches (search-patches "mpc123-initialize-ao.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-replace
diff --git a/gnu/packages/mpd.scm b/gnu/packages/mpd.scm
index 1af66e039c..4860325b56 100644
--- a/gnu/packages/mpd.scm
+++ b/gnu/packages/mpd.scm
@@ -42,7 +42,6 @@
   #:use-module (gnu packages ncurses)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages python)
-  #:use-module (gnu packages autotools)
   #:use-module (gnu packages pulseaudio)
   #:use-module (gnu packages databases)
   #:use-module (gnu packages video)
@@ -181,7 +180,7 @@ terminal using ncurses.")
 (define-public ncmpcpp
   (package
     (name "ncmpcpp")
-    (version "0.7.3")
+    (version "0.7.4")
     (source (origin
               (method url-fetch)
               (uri
@@ -189,7 +188,7 @@ terminal using ncurses.")
                               version ".tar.bz2"))
               (sha256
                (base32
-                "04mj6r0whikliblxfbz92pibwcd7a3ywkryf01a89zd4bi1jk2rc"))))
+                "0qqy3w2vw3i9rxz0z8n0plmwwfv6gzrxip86l894l1xbvzqja16p"))))
     (build-system gnu-build-system)
     (inputs `(("libmpdclient" ,libmpdclient)
               ("boost"  ,boost)
@@ -198,19 +197,10 @@ terminal using ncurses.")
               ("taglib" ,taglib)
               ("icu4c" ,icu4c)))
     (native-inputs
-     `(("pkg-config" ,pkg-config)
-       ("automake" ,automake)
-       ("autoconf" ,autoconf)
-       ("libtool" ,libtool)))
+     `(("pkg-config" ,pkg-config)))
     (arguments
      '(#:configure-flags
-       '("BOOST_LIB_SUFFIX=" "--with-taglib")
-       #:phases
-       (modify-phases %standard-phases
-        (add-after 'unpack 'autogen
-         (lambda _
-           (setenv "NOCONFIGURE" "true")
-           (zero? (system* "sh" "autogen.sh")))))))
+       '("BOOST_LIB_SUFFIX=" "--with-taglib")))
     (synopsis "Featureful ncurses based MPD client inspired by ncmpc")
     (description "Ncmpcpp is an mpd client with a UI very similar to ncmpc,
 but it provides new useful features such as support for regular expressions
diff --git a/gnu/packages/mpi.scm b/gnu/packages/mpi.scm
index abe4fac470..262330ecd7 100644
--- a/gnu/packages/mpi.scm
+++ b/gnu/packages/mpi.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015 Eric Bavier <bavier@member.fsf.org>
-;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014 Ian Denhardt <ian@zenhack.net>
 ;;; Copyright © 2016 Andreas Enge <andreas@enge.fr>
 ;;;
@@ -41,15 +41,15 @@
 (define-public hwloc
   (package
     (name "hwloc")
-    (version "1.11.1")
+    (version "1.11.2")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://www.open-mpi.org/software/hwloc/v"
+              (uri (string-append "https://www.open-mpi.org/software/hwloc/v"
                                   (version-major+minor version)
                                   "/downloads/hwloc-" version ".tar.bz2"))
               (sha256
                (base32
-                "03vcr9f98z45xfkk34x376mfrwyi7ff4ay60gvn4v95sqihl0qa8"))))
+                "1y7c3ysiin0rw0sj6dbxkvjg92j4by36rykvf0vmh91q2rmrn0lc"))))
     (build-system gnu-build-system)
     (inputs
      `(("libx11" ,libx11)
@@ -79,7 +79,7 @@
                                 '("lib/pkgconfig/hwloc.pc" "lib/libhwloc.la"))
                 (("-lnuma" lib)
                  (string-append "-L" numa "/lib " lib)))))))))
-    (home-page "http://www.open-mpi.org/projects/hwloc/")
+    (home-page "https://www.open-mpi.org/projects/hwloc/")
     (synopsis "Abstraction of hardware architectures")
     (description
      "hwloc provides a portable abstraction (across OS,
diff --git a/gnu/packages/multiprecision.scm b/gnu/packages/multiprecision.scm
index ba2211974b..46540be5c4 100644
--- a/gnu/packages/multiprecision.scm
+++ b/gnu/packages/multiprecision.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2012, 2013, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -39,8 +40,7 @@
             (sha256
              (base32
               "12b9s4jn48gbar6dbs5qrlmljdmnq43xy3ji9yjzic0mwp6dmnk8"))
-            (patches (map search-patch
-                          '("gmp-faulty-test.patch")))))
+            (patches (search-patches "gmp-faulty-test.patch"))))
    (build-system gnu-build-system)
    (native-inputs `(("m4" ,m4)))
    (outputs '("out" "debug"))
@@ -74,9 +74,8 @@ cryptography and computational algebra.")
               (sha256
                (base32
                 "0r5pp27cy7ch3dg5v0rsny8bib1zfvrza6027g2mp5f6v8pd6mli"))
-              (patches (map search-patch
-                            '("gmp-arm-asm-nothumb.patch"
-                              "gmp-faulty-test.patch")))))))
+              (patches (search-patches "gmp-arm-asm-nothumb.patch"
+                                       "gmp-faulty-test.patch"))))))
 
 (define-public mpfr
   (package
@@ -119,3 +118,28 @@ floating-point computations with correct rounding.")
 It supports arbitrarily high precision and it correctly rounds the results.")
    (license lgpl3+)
    (home-page "http://mpc.multiprecision.org/")))
+
+(define-public mpfi
+  (package
+    (name "mpfi")
+    (version "1.5.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://gforge.inria.fr/frs/download.php/"
+                                  "file/30130/mpfi-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1g2q6i7dqx40p4gw11da6jgfcbzmm26wxc69fwv8zpcdyg32a9za"))))
+    (build-system gnu-build-system)
+    (propagated-inputs `(("gmp" ,gmp)   ; <mpfi.h> refers to both
+                         ("mpfr" ,mpfr)))
+    (synopsis "C library for arbitrary precision interval arithmetic")
+    (description "MPFI is intended to be a portable library written in C for
+arbitrary precision interval arithmetic with intervals represented using MPFR
+reliable floating-point numbers.  It is based on the GNU MP library and on the
+MPFR library.  The purpose of an arbitrary precision interval arithmetic is on
+the one hand to get guaranteed results, thanks to interval computation, and on
+the other hand to obtain accurate results, thanks to multiple precision
+arithmetic.")
+    (license lgpl2.1+)
+    (home-page "https://perso.ens-lyon.fr/nathalie.revol/software.html")))
diff --git a/gnu/packages/music.scm b/gnu/packages/music.scm
index 1fa142120e..95f52c5dd6 100644
--- a/gnu/packages/music.scm
+++ b/gnu/packages/music.scm
@@ -59,6 +59,7 @@
   #:use-module (gnu packages gl)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gnome)
+  #:use-module (gnu packages graphics)
   #:use-module (gnu packages gtk)
   #:use-module (gnu packages guile)
   #:use-module (gnu packages image)
@@ -85,12 +86,79 @@
   #:use-module (gnu packages texlive)
   #:use-module (gnu packages video)
   #:use-module (gnu packages web)
+  #:use-module (gnu packages wxwidgets)
   #:use-module (gnu packages xml)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages xiph)
   #:use-module (gnu packages zip)
   #:use-module ((srfi srfi-1) #:select (last)))
 
+(define-public aria-maestosa
+  (package
+    (name "aria-maestosa")
+    (version "1.4.11")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://sourceforge/ariamaestosa/ariamaestosa/"
+                                  version "/AriaSrc-" version ".tar.bz2"))
+              (sha256
+               (base32
+                "0gf9z96z83jiabxhpl856j15vl9flfgs6x1r0r6hc7g2xvwag0vy"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f  ;no tests
+       #:phases
+       ;; TODO: Add scons-build-system and use it here.
+       (modify-phases %standard-phases
+         (delete 'configure)
+         (add-after 'unpack 'scons-propagate-environment
+           (lambda _
+             ;; By design, SCons does not, by default, propagate
+             ;; environment variables to subprocesses.  See:
+             ;; <http://comments.gmane.org/gmane.linux.distributions.nixos/4969>
+             ;; Here, we modify the SConstruct file to arrange for
+             ;; environment variables to be propagated.
+             (substitute* "SConstruct"
+               (("env = Environment\\(\\)")
+                "env = Environment(ENV=os.environ)")
+               ;; Scons errors out when copying subdirectories from Resources,
+               ;; so we move them instead.
+               (("Copy") "Move")
+               ;; We move the "score" and "Documentation" directories at once,
+               ;; so we have to ignore files contained therein.
+               (("if \".svn\" in file" line)
+                (string-append line
+                               " or \"score/\" in file"
+                               " or \"Documentation/\" in file")))
+             #t))
+         (replace 'build (lambda _ (zero? (system* "scons"))))
+         (replace 'install
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out")))
+               (and
+                (zero? (system* "scons"
+                                (string-append "prefix=" out)
+                                "install"))
+                ;; Fix directory permissions
+                (begin
+                  (chmod (string-append out "/share/Aria/Documentation") #o555)
+                  (chmod (string-append out "/share/Aria/score") #o555)
+                  #t))))))))
+    (inputs
+     `(("wxwidgets" ,wxwidgets)
+       ("glib" ,glib)
+       ("alsa-lib" ,alsa-lib)))
+    (native-inputs
+     `(("scons" ,scons)
+       ("pkg-config" ,pkg-config)))
+    (home-page "http://ariamaestosa.sourceforge.net/")
+    (synopsis "MIDI sequencer and editor")
+    (description
+     "Aria Maestosa is a MIDI sequencer and editor.  It lets you compose, edit
+and play MIDI files with a few clicks in a user-friendly interface offering
+score, keyboard, guitar, drum and controller views.")
+    (license license:gpl3+)))
+
 (define-public cmus
   (package
     (name "cmus")
@@ -621,19 +689,47 @@ your own lessons.")
 Editor.  It is compatible with Power Tab Editor 1.7 and Guitar Pro.")
     (license license:gpl3+)))
 
+(define-public synthv1
+  (package
+    (name "synthv1")
+    (version "0.7.4")
+    (source (origin
+              (method url-fetch)
+              (uri
+               (string-append "mirror://sourceforge/synthv1/synthv1-"
+                              version ".tar.gz"))
+              (sha256
+               (base32
+                "16n0v4jk0ilirq84rrildvdwqxgxav78rk58ilhl622v5n893c7w"))))
+    (build-system gnu-build-system)
+    ;; There are no tests.
+    (arguments `(#:tests? #f))
+    (inputs
+     `(("jack" ,jack-1)
+       ("lv2" ,lv2)
+       ("alsa-lib" ,alsa-lib)
+       ("liblo" ,liblo)
+       ("qt" ,qt)))
+    (home-page "http://synthv1.sourceforge.net")
+    (synopsis "Polyphonic subtractive synthesizer")
+    (description
+     "Synthv1 is an old-school subtractive polyphonic synthesizer with four
+oscillators and stereo effects.")
+    (license license:gpl2+)))
+
 (define-public setbfree
   (package
     (name "setbfree")
-    (version "0.8.0")
+    (version "0.8.1")
     (source (origin
               (method url-fetch)
               (uri
-               (string-append
-                "https://github.com/pantherb/setBfree/releases/download/v"
-                version "/setbfree-" version ".tar.gz"))
+               (string-append "https://github.com/pantherb/setBfree/archive/v"
+                              version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
               (sha256
                (base32
-                "045bgp7qsigpbrhk7qvgvliwiy26sajifwn7f2jvk90ckfqnlw4b"))))
+                "0hj0rqk5yd4fzs7bwy6a6nhqgrmcggkjcr4il76rxy92r7nwabf3"))))
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f ; no "check" target
@@ -673,6 +769,46 @@ modification devices that brought world-wide fame to the names and products of
 Laurens Hammond and Don Leslie.")
     (license license:gpl2+)))
 
+(define-public beast
+  (package
+    (name "beast")
+    (version "0.10.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://testbit.eu/pub/dists/beast/beast-"
+                                  version ".tar.xz"))
+              (sha256
+               (base32
+                "1jzzmfwssklzw8fvvil04n8csc0zm99fnd9p2xa7c0xchg37lvhn"))))
+    (build-system gnu-build-system)
+    (inputs
+     `(("rapicorn" ,rapicorn)
+       ("guile" ,guile-1.8)
+       ("python" ,python-2)
+       ("cython" ,python2-cython)
+       ("libgnomecanvas" ,libgnomecanvas)
+       ("libogg" ,libogg)
+       ("libmad" ,libmad)
+       ("flac" ,flac)
+       ("alsa-lib" ,alsa-lib)
+       ("libvorbis" ,libvorbis)
+       ("gettext" ,gnu-gettext)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("glib:bin" ,glib "bin")
+       ("perl" ,perl)
+       ("perl-xml-parser" ,perl-xml-parser)))
+    (home-page "https://testbit.eu/wiki/Beast_Home")
+    (synopsis "Music composition and modular synthesis environment")
+    (description
+     "Beast is a music composition and modular synthesis application.  It
+supports a wide range of standards in the field, such as MIDI, various audio
+file formats and LADSPA modules.  It allows for multitrack editing, real-time
+synthesis, 32bit audio rendering, precise timing down to sample granularity,
+on-demand and partial loading of wave files, on the fly decoding, stereo
+mixing, FFT scopes, MIDI automation and full scriptability in Scheme.")
+    (license license:gpl3+)))
+
 (define-public bristol
   (package
     (name "bristol")
@@ -734,7 +870,7 @@ is subjective.")
                           (string-append "PREFIX="
                                          (assoc-ref %outputs "out"))
                           (string-append "SWT_PATH="
-                                         (assoc-ref %build-inputs "swt")
+                                         (assoc-ref %build-inputs "java-swt")
                                          "/share/java/swt.jar"))
        #:tests? #f ;no "check" target
        #:parallel-build? #f ;not supported
@@ -749,11 +885,11 @@ is subjective.")
                (string-append "GCJFLAGS=-fsource=1.4 -fPIC " rest))
               (("PROPERTIES\\?=")
                (string-append "PROPERTIES?= -Dswt.library.path="
-                              (assoc-ref inputs "swt") "/lib"))
+                              (assoc-ref inputs "java-swt") "/lib"))
               (("\\$\\(GCJ\\) -o") "$(GCJ) $(LDFLAGS) -o"))
             #t)))))
     (inputs
-     `(("swt" ,swt)))
+     `(("java-swt" ,java-swt)))
     (native-inputs
      `(("gcj" ,gcj)
        ("pkg-config" ,pkg-config)))
@@ -825,7 +961,7 @@ projects.")
 (define-public frescobaldi
   (package
     (name "frescobaldi")
-    (version "2.18.2")
+    (version "2.19.0")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -833,7 +969,7 @@ projects.")
                     version "/frescobaldi-" version ".tar.gz"))
               (sha256
                (base32
-                "1yns7nq2a2hz5rv4xjp21bgcdi1xj6fq48lqjrld7ypqqi5nfjp5"))))
+                "1rnk8i8dlshzx16n2qxcsqcs7kywgyazzyzw2vy4vp2gsm9vs9ml"))))
     (build-system python-build-system)
     (inputs
      `(("lilypond" ,lilypond)
@@ -945,7 +1081,7 @@ instrument or MIDI file player.")
 (define-public zynaddsubfx
   (package
     (name "zynaddsubfx")
-    (version "2.5.3")
+    (version "2.5.4")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -953,7 +1089,7 @@ instrument or MIDI file player.")
                     version "/zynaddsubfx-" version ".tar.bz2"))
               (sha256
                (base32
-                "04da54p19p7f5wm6vm7abbjbsil1qf7n5f4adj01jm6b0wqigvgb"))))
+                "16llaa2wg2gbgjhwp3632b2vx9jvanj4csv7d41k233ms6d1sjq1"))))
     (build-system cmake-build-system)
     (arguments
      `(#:phases
@@ -1055,7 +1191,7 @@ improves on support for JACK features, such as JACK MIDI.")
                           version ".tar.gz"))
       (sha256
        (base32 "1dhphsya41rv8z6yqcv9l6fwbslsds4zh1y56zizi39nd996d40v"))
-      (patches (list (search-patch "cursynth-wave-rand.patch")))))
+      (patches (search-patches "cursynth-wave-rand.patch"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)))
     ;; TODO: See https://github.com/iyoko/cursynth/issues/4 which currently
@@ -1073,14 +1209,14 @@ computer's keyboard.")
 (define-public qtractor
   (package
     (name "qtractor")
-    (version "0.7.5")
+    (version "0.7.7")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://downloads.sourceforge.net/qtractor/"
                                   "qtractor-" version ".tar.gz"))
               (sha256
                (base32
-                "0drqzp1rbqmqiwdzc9n3307y8rm882fha3awy5qlvir5ma2mwl80"))))
+                "0q8kvy1ynlg64v1w7jxix1rpq0lp2ixgb2y8cbbwxd2b28r3r2vl"))))
     (build-system gnu-build-system)
     (arguments `(#:tests? #f)) ; no "check" target
     (inputs
diff --git a/gnu/packages/networking.scm b/gnu/packages/networking.scm
index a4f431a0b1..306a3a0218 100644
--- a/gnu/packages/networking.scm
+++ b/gnu/packages/networking.scm
@@ -5,6 +5,7 @@
 ;;; Copyright © 2015 Stefan Reichör <stefan@xsteve.at>
 ;;; Copyright © 2016 Raimon Grau <raimonster@gmail.com>
 ;;; Copyright © 2016 Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>
+;;; Copyright   2016 John Darrington <jmd@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -32,6 +33,26 @@
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages compression))
 
+(define-public macchanger
+  (package
+    (name "macchanger")
+    (version "1.6.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://gnu/"
+                                  name "/" name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1xsiivjjyhqcs6dyjcshrnxlgypvyfzacjz7gcjgl88xiw9lylri"))))
+    (build-system gnu-build-system)
+    (home-page "http://www.gnu.org/software/macchanger")
+    (synopsis "Display or change the MAC address of networking devices")
+    (description "GNU MAC Changer is a utility for viewing and changing MAC
+addresses of networking devices.  New addresses may be set explicitly or
+randomly.  They can include MAC addresses of the same or other hardware vendors
+or, more generally, MAC addresses of the same category of hardware.") 
+    (license license:gpl2+)))
+
 (define-public miredo
   (package
     (name "miredo")
diff --git a/gnu/packages/ninja.scm b/gnu/packages/ninja.scm
index ea5488afc9..cfcc6d5a51 100644
--- a/gnu/packages/ninja.scm
+++ b/gnu/packages/ninja.scm
@@ -37,8 +37,8 @@
               (sha256
                (base32
                 "1h3yfwcfl61v493vna6jia2fizh8rpig7qw2504cvkr6gid3p5bw"))
-              (patches (map search-patch
-                            '("ninja-zero-mtime.patch" "ninja-tests.patch")))))
+              (patches (search-patches "ninja-zero-mtime.patch"
+                                       "ninja-tests.patch"))))
     (build-system gnu-build-system)
     (native-inputs `(("python" ,python-2)))
     (arguments
diff --git a/gnu/packages/node.scm b/gnu/packages/node.scm
index bde1e1e197..2f269d08b1 100644
--- a/gnu/packages/node.scm
+++ b/gnu/packages/node.scm
@@ -1,7 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 Cyrill Schenkel <cyrill.schenkel@gmail.com>
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
-;;; Copyright © 2015 David Thompson <davet@gnu.org>
+;;; Copyright © 2015, 2016 David Thompson <davet@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -36,41 +36,74 @@
 (define-public node
   (package
     (name "node")
-    (version "0.12.7")
+    (version "6.0.0")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://nodejs.org/dist/v" version
                                   "/node-v" version ".tar.gz"))
               (sha256
                (base32
-                "17gk29zbw58l0sjjfw86acp39pkiblnq0gsq1jdrd70w0pgn8gdj"))))
+                "0cpw7ng193jgfbw2g1fd0kcglmjjkbj4xb89g00z8zz0lj0nvdbd"))))
     (build-system gnu-build-system)
     (arguments
      ;; TODO: Package http_parser and add --shared-http-parser.
-     '(#:configure-flags '("--shared-openssl" "--shared-zlib" "--shared-libuv")
+     '(#:configure-flags '("--shared-openssl"
+                           "--shared-zlib"
+                           "--shared-libuv"
+                           "--without-snapshot")
        #:phases
        (modify-phases %standard-phases
-        (replace 'configure
-         ;; Node's configure script is actually a python script, so we can't
-         ;; run it with bash.
-         (lambda* (#:key outputs (configure-flags '()) inputs
-                   #:allow-other-keys)
-           (let* ((prefix (assoc-ref outputs "out"))
-                  (flags (cons (string-append "--prefix=" prefix)
-                               configure-flags)))
-             (format #t "build directory: ~s~%" (getcwd))
-             (format #t "configure flags: ~s~%" flags)
-             ;; Node's configure script expects the CC environment variable to
-             ;; be set.
-             (setenv "CC" (string-append (assoc-ref inputs "gcc") "/bin/gcc"))
-             (zero? (apply system*
-                           (string-append (assoc-ref inputs "python")
-                                          "/bin/python")
-                           "./configure" flags))))))))
+         (add-before 'configure 'patch-files
+           (lambda* (#:key inputs #:allow-other-keys)
+             ;; Fix hardcoded /bin/sh references.
+             (substitute* '("lib/child_process.js"
+                            "lib/internal/v8_prof_polyfill.js"
+                            "test/parallel/test-stdio-closed.js")
+               (("'/bin/sh'")
+                (string-append "'" (which "bash") "'")))
+
+             ;; Fix hardcoded /usr/bin/env references.
+             (substitute* '("test/parallel/test-child-process-default-options.js"
+                            "test/parallel/test-child-process-env.js"
+                            "test/parallel/test-child-process-exec-env.js")
+               (("'/usr/bin/env'")
+                (string-append "'" (which "env") "'")))
+
+             ;; Having the build fail because of linter errors is insane!
+             (substitute* '("Makefile")
+               (("	\\$\\(MAKE\\) jslint") "")
+               (("	\\$\\(MAKE\\) cpplint\n") ""))
+
+             ;; FIXME: These tests fail in the build container, but they don't
+             ;; seem to be indicative of real problems in practice.
+             (for-each delete-file
+                       '("test/parallel/test-cluster-master-error.js"
+                         "test/parallel/test-cluster-master-kill.js"
+                         "test/parallel/test-npm-install.js"
+                         "test/parallel/test-stdout-close-unref.js"
+                         "test/sequential/test-child-process-emfile.js"))
+             #t))
+         (replace 'configure
+           ;; Node's configure script is actually a python script, so we can't
+           ;; run it with bash.
+           (lambda* (#:key outputs (configure-flags '()) inputs
+                     #:allow-other-keys)
+             (let* ((prefix (assoc-ref outputs "out"))
+                    (flags (cons (string-append "--prefix=" prefix)
+                                 configure-flags)))
+               (format #t "build directory: ~s~%" (getcwd))
+               (format #t "configure flags: ~s~%" flags)
+               ;; Node's configure script expects the CC environment variable to
+               ;; be set.
+               (setenv "CC" (string-append (assoc-ref inputs "gcc") "/bin/gcc"))
+               (zero? (apply system*
+                             (string-append (assoc-ref inputs "python")
+                                            "/bin/python")
+                             "configure" flags))))))))
     (native-inputs
      `(("python" ,python-2)
        ("perl" ,perl)
-       ("gcc" ,gcc-4.9)
+       ("procps" ,procps)
        ("util-linux" ,util-linux)
        ("which" ,which)))
     (inputs
diff --git a/gnu/packages/nvi.scm b/gnu/packages/nvi.scm
index 128715f6ac..999b553733 100644
--- a/gnu/packages/nvi.scm
+++ b/gnu/packages/nvi.scm
@@ -37,9 +37,9 @@
                          ".tar.bz2"))
         (sha256
           (base32 "0nbbs1inyrqds0ywn3ln5slv54v5zraq7lszkg8nsavv4kivhh9l"))
-        (patches (list (search-patch "nvi-assume-preserve-path.patch")
-                       (search-patch "nvi-dbpagesize-binpower.patch")
-                       (search-patch "nvi-db4.patch")))
+        (patches (search-patches "nvi-assume-preserve-path.patch"
+                                 "nvi-dbpagesize-binpower.patch"
+                                 "nvi-db4.patch"))
         (snippet
           ;; Create a wrapper for the configure script, make it executable.
           '(let ((conf-wrap (open-output-file "configure")))
diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 4b5ac617d5..5d489532f7 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -633,8 +633,7 @@ to the other.")
               (sha256
                (base32
                 "02abg1lsnwvjg3igdyb8qjgr5kv1nbwl4gaf8mdinzfii5p82721"))
-              (patches
-               (list (search-patch "ocaml-findlib-make-install.patch")))))
+              (patches (search-patches "ocaml-findlib-make-install.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("camlp4" ,camlp4)
diff --git a/gnu/packages/openldap.scm b/gnu/packages/openldap.scm
index d416a43857..429078fc92 100644
--- a/gnu/packages/openldap.scm
+++ b/gnu/packages/openldap.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2013 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -33,6 +34,7 @@
 
 (define-public openldap
   (package
+   (replacement openldap-2.4.44)
    (name "openldap")
    (version "2.4.42")
    (source (origin
@@ -76,3 +78,24 @@
     "OpenLDAP is a free implementation of the Lightweight Directory Access Protocol.")
    (license openldap2.8)
    (home-page "http://www.openldap.org/")))
+
+(define openldap-2.4.44
+  (package
+    (inherit openldap)
+    (replacement #f)
+    (source
+      (let ((version "2.4.44"))
+        (origin
+          (method url-fetch)
+          (uri (list (string-append
+                      "ftp://mirror.switch.ch/mirror/OpenLDAP/"
+                      "openldap-release/openldap-" version ".tgz")
+                     (string-append
+                      "ftp://ftp.OpenLDAP.org/pub/OpenLDAP/"
+                      "openldap-release/openldap-" version ".tgz")
+                     (string-append
+                      "ftp://ftp.dti.ad.jp/pub/net/OpenLDAP/"
+                      "openldap-release/openldap-" version ".tgz")))
+          (sha256
+           (base32
+            "0044p20hx07fwgw2mbwj1fkx04615hhs1qyx4mawj2bhqvrnppnp")))))))
diff --git a/gnu/packages/openstack.scm b/gnu/packages/openstack.scm
index 947abf31a4..780fb7f252 100644
--- a/gnu/packages/openstack.scm
+++ b/gnu/packages/openstack.scm
@@ -137,16 +137,16 @@ guidelines}.")
 (define-public python-mox3
   (package
     (name "python-mox3")
-    (version "0.13.0")
+    (version "0.14.0")
     (source
       (origin
         (method url-fetch)
         (uri (pypi-uri "mox3" version))
         (sha256
           (base32
-           "0hj57374r239cj1zbzpxw7mj0yfblz55jdfrc2p1h8j7xng0319j"))))
+           "0njmh40i1lg5mzn9hc2ax83adj6dli455j6xifilrw27c4wlkjzx"))))
     (build-system python-build-system)
-    (inputs
+    (native-inputs
       `(("python-fixtures" ,python-fixtures)
         ("python-pbr" ,python-pbr)
         ("python-setuptools" ,python-setuptools)
@@ -156,11 +156,14 @@ guidelines}.")
     (synopsis "Mock object framework for Python")
     (description
       "Mox3 is an unofficial port of the Google mox framework
-(http://code.google.com/p/pymox/) to Python 3. It was meant to be as compatible
-with mox as possible, but small enhancements have been made. The library was
+(http://code.google.com/p/pymox/) to Python 3.  It was meant to be as compatible
+with mox as possible, but small enhancements have been made.  The library was
 tested on Python version 3.2, 2.7 and 2.6.")
     (license asl2.0)))
 
+(define-public python2-mox3
+  (package-with-python2 python-mox3))
+
 (define-public python-os-client-config
   (package
     (name "python-os-client-config")
@@ -197,9 +200,6 @@ tested on Python version 3.2, 2.7 and 2.6.")
 (define-public python2-os-client-config
   (package-with-python2 python-os-client-config))
 
-(define-public python2-mox3
-  (package-with-python2 python-mox3))
-
 (define-public python-os-testr
   (package
     (name "python-os-testr")
@@ -266,20 +266,21 @@ portions of your testing code.")
 (define-public python-stevedore
   (package
     (name "python-stevedore")
-    (version "1.10.0")
+    (version "1.12.0")
     (source
      (origin
        (method url-fetch)
        (uri (pypi-uri "stevedore" version))
        (sha256
          (base32
-          "17vpffcnk56sj86d2n3vz5bprcc9bswilgd0awnm7jp073pqkmpm"))))
+          "0999zvawaapzg6givjhn7vjscdwblcs73wf28wq1wb4g5mbb5phv"))))
     (build-system python-build-system)
     (propagated-inputs
       `(("python-six" ,python-six)))
     (inputs
-      `(("python-pbr" ,python-pbr)
-        ("python-setuptools" ,python-setuptools)
+      `(("python-pbr" ,python-pbr)))
+    (native-inputs
+      `(("python-setuptools" ,python-setuptools)
         ;; Tests
         ("python-docutils" ,python-docutils)
         ("python-mock" ,python-mock)
@@ -289,9 +290,9 @@ portions of your testing code.")
     (synopsis "Manage dynamic plugins for Python applications")
     (description
       "Python makes loading code dynamically easy, allowing you to configure
-and extend your application by discovering and loading extensions (“plugins”)
+and extend your application by discovering and loading extensions (\"plugins\")
 at runtime.  Many applications implement their own library for doing this,
-using __import__ or importlib.  stevedore avoids creating yet another extension
+using __import__ or importlib.  Stevedore avoids creating yet another extension
 mechanism by building on top of setuptools entry points.  The code for managing
 entry points tends to be repetitive, though, so stevedore provides manager
 classes for implementing common patterns for using dynamically loaded
diff --git a/gnu/packages/orpheus.scm b/gnu/packages/orpheus.scm
index 7d4b1cac63..069d3e548a 100644
--- a/gnu/packages/orpheus.scm
+++ b/gnu/packages/orpheus.scm
@@ -40,7 +40,7 @@
       (sha256
        (base32
         "1xbgxq8fybwhm51nw9hvvrgi873qzkc2qvmy15d2m2hw2yqa99hq"))
-      (patches (list (search-patch "orpheus-cast-errors-and-includes.patch")))))
+      (patches (search-patches "orpheus-cast-errors-and-includes.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("ncurses" ,ncurses)
diff --git a/gnu/packages/ots.scm b/gnu/packages/ots.scm
index 1c0d4a71f4..f1900746b6 100644
--- a/gnu/packages/ots.scm
+++ b/gnu/packages/ots.scm
@@ -40,8 +40,7 @@
                            ".tar.gz"))
        (sha256
         (base32 "0dz1ccd7ymzk4swz1aly4im0k3pascnshmgg1whd2rk14li8v47a"))
-       (patches
-        (list (search-patch "ots-no-include-missing-file.patch")))))
+       (patches (search-patches "ots-no-include-missing-file.patch"))))
 
     (build-system gnu-build-system)
     (arguments
diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm
index 38c9bdb7d1..0a765cd080 100644
--- a/gnu/packages/package-management.scm
+++ b/gnu/packages/package-management.scm
@@ -195,14 +195,15 @@ also a distribution thereof.  It includes a virtual machine image.  Besides
 the usual package management features, it also supports transactional
 upgrades and roll-backs, per-user profiles, and much more.  It is based on
 the Nix package manager.")
-    (license gpl3+)))
+    (license gpl3+)
+    (properties '((ftp-server . "alpha.gnu.org")))))
 
 (define guix-devel
   ;; Development version of Guix.
   ;;
   ;; Note: use a very short commit id; with a longer one, the limit on
   ;; hash-bang lines would be exceeded while running the tests.
-  (let ((commit "761139354798303c605964b896c250a01486b00a"))
+  (let ((commit "80627f51f0238b9450745f4e642172d059ca5bb5"))
     (package (inherit guix-0.10.0)
       (version (string-append "0.10.0-0." (string-take commit 4)))
       (source (origin
@@ -212,7 +213,7 @@ the Nix package manager.")
                       (commit commit)))
                 (sha256
                  (base32
-                  "1wvy9kms3v6k7cybw6489mqk161lv8d03qgmmxbmdgiwjmjxbzbn"))
+                  "102gdbx5imx0zab7i5dwa1z9j1diblinaaja09dp3q30770iyxj9"))
                 (file-name (string-append "guix-" version "-checkout"))))
       (arguments
        (substitute-keyword-arguments (package-arguments guix-0.10.0)
diff --git a/gnu/packages/parallel.scm b/gnu/packages/parallel.scm
index 4648010bf1..828bd26cf8 100644
--- a/gnu/packages/parallel.scm
+++ b/gnu/packages/parallel.scm
@@ -74,8 +74,8 @@ and they are executed on lists of files, hosts, users or other items.")
             (sha256
              (base32
               "1rmi35l4img00dr4vic8cv8s7b6n1yx1mkq2s7kjf5hvqdh6s2ki"))
-            (patches (list
-             (search-patch "slurm-configure-remove-nonfree-contribs.patch")))
+            (patches (search-patches
+                      "slurm-configure-remove-nonfree-contribs.patch"))
             (modules '((guix build utils)))
             (snippet
              '(begin
diff --git a/gnu/packages/patches/abiword-link-plugins-against-backend.patch b/gnu/packages/patches/abiword-link-plugins-against-backend.patch
deleted file mode 100644
index fb8fbfc98b..0000000000
--- a/gnu/packages/patches/abiword-link-plugins-against-backend.patch
+++ /dev/null
@@ -1,639 +0,0 @@
-Link plugins against libabiword. This is because --no-undefined is passed to
-the linker when linking and without libabiword, it would fail.
-
---- a/plugins/aiksaurus/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/aiksaurus/Makefile.in	2014-09-06 14:58:36.480413350 +0200
-@@ -422,7 +422,8 @@
- plugin_LTLIBRARIES = aiksaurus.la
- aiksaurus_la_LIBADD = \
- 	$(platform_lib) \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- aiksaurus_la_LDFLAGS = \
- 	$(AIKSAURUS_LIBS) \
-
---- a/plugins/applix/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/applix/Makefile.in	2014-09-06 14:58:54.416413938 +0200
-@@ -425,7 +425,8 @@
- @APPLIX_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @APPLIX_BUILTIN_FALSE@plugin_LTLIBRARIES = applix.la
- applix_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- applix_la_LDFLAGS = \
- 	$(APPLIX_LIBS) \
-
---- a/plugins/babelfish/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/babelfish/Makefile.in	2014-09-06 14:59:09.220414422 +0200
-@@ -425,7 +425,8 @@
- @BABELFISH_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @BABELFISH_BUILTIN_FALSE@plugin_LTLIBRARIES = babelfish.la
- babelfish_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- babelfish_la_LDFLAGS = \
- 	$(BABELFISH_LIBS) \
-
---- a/plugins/bmp/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/bmp/Makefile.in	2014-09-06 14:59:53.928415886 +0200
-@@ -425,7 +425,8 @@
- @BMP_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @BMP_BUILTIN_FALSE@plugin_LTLIBRARIES = bmp.la
- bmp_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- bmp_la_LDFLAGS = \
- 	$(BMP_LIBS) \
-
---- a/plugins/clarisworks/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/clarisworks/Makefile.in	2014-09-06 15:00:06.148416286 +0200
-@@ -427,7 +427,8 @@
- @CLARISWORKS_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @CLARISWORKS_BUILTIN_FALSE@plugin_LTLIBRARIES = clarisworks.la
- clarisworks_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- clarisworks_la_LDFLAGS = \
- 	$(CLARISWORKS_LIBS) \
-
---- a/plugins/collab/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/collab/Makefile.in	2014-09-06 15:02:04.000420145 +0200
-@@ -428,7 +428,8 @@
- @TOOLKIT_COCOA_FALSE@plugin_LTLIBRARIES = collab.la
- @TOOLKIT_COCOA_FALSE@collab_la_LIBADD = \
- @TOOLKIT_COCOA_FALSE@	backends/libbackends.la \
--@TOOLKIT_COCOA_FALSE@	core/libcore.la
-+@TOOLKIT_COCOA_FALSE@	core/libcore.la \
-+@TOOLKIT_COCOA_FALSE@	@top_builddir@/src/libabiword-2.8.la
- 
- @TOOLKIT_COCOA_FALSE@collab_la_LDFLAGS = \
- @TOOLKIT_COCOA_FALSE@	$(COLLAB_LIBS) \
-
---- a/plugins/command/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/command/Makefile.in	2014-09-06 15:02:41.208421363 +0200
-@@ -420,7 +420,8 @@
- @TOOLKIT_COCOA_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @TOOLKIT_COCOA_FALSE@plugin_LTLIBRARIES = command.la
- @TOOLKIT_COCOA_FALSE@command_la_LIBADD = \
--@TOOLKIT_COCOA_FALSE@	xp/libxp.la
-+@TOOLKIT_COCOA_FALSE@	xp/libxp.la \
-+@TOOLKIT_COCOA_FALSE@	@top_builddir@/src/libabiword-2.8.la
- 
- @TOOLKIT_COCOA_FALSE@command_la_LDFLAGS = \
- @TOOLKIT_COCOA_FALSE@	$(COMMAND_LIBS) \
-
---- a/plugins/docbook/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/docbook/Makefile.in	2014-09-06 15:02:52.128421720 +0200
-@@ -425,7 +425,8 @@
- @DOCBOOK_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @DOCBOOK_BUILTIN_FALSE@plugin_LTLIBRARIES = docbook.la
- docbook_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- docbook_la_LDFLAGS = \
- 	$(DOCBOOK_LIBS) \
-
---- a/plugins/eml/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/eml/Makefile.in	2014-09-06 15:03:02.760422068 +0200
-@@ -425,7 +425,8 @@
- @EML_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @EML_BUILTIN_FALSE@plugin_LTLIBRARIES = eml.la
- eml_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- eml_la_LDFLAGS = \
- 	$(EML_LIBS) \
-
---- a/plugins/freetranslation/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/freetranslation/Makefile.in	2014-09-06 15:03:17.656422556 +0200
-@@ -427,7 +427,8 @@
- @FREETRANSLATION_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @FREETRANSLATION_BUILTIN_FALSE@plugin_LTLIBRARIES = freetranslation.la
- freetranslation_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- freetranslation_la_LDFLAGS = \
- 	$(FREETRANSLATION_LIBS) \
-
---- a/plugins/garble/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/garble/Makefile.in	2014-09-06 15:03:48.192423556 +0200
-@@ -427,7 +427,8 @@
- @TOOLKIT_COCOA_FALSE@plugin_LTLIBRARIES = garble.la
- @TOOLKIT_COCOA_FALSE@garble_la_LIBADD = \
- @TOOLKIT_COCOA_FALSE@	xp/libxp.la \
--@TOOLKIT_COCOA_FALSE@	$(GARBLE_LIBS) $(PNG_LIBS) -ljpeg
-+@TOOLKIT_COCOA_FALSE@	$(GARBLE_LIBS) $(PNG_LIBS) -ljpeg \
-+@TOOLKIT_COCOA_FALSE@	@top_builddir@/src/libabiword-2.8.la
- 
- @TOOLKIT_COCOA_FALSE@garble_la_LDFLAGS = \
- @TOOLKIT_COCOA_FALSE@	$(GARBLE_LIBS) \
-
---- a/plugins/gda/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/gda/Makefile.in	2014-09-06 15:04:08.012424205 +0200
-@@ -419,7 +419,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = gda.la
- gda_la_LIBADD = \
--	unix/libunix.la
-+	unix/libunix.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- gda_la_LDFLAGS = \
- 	$(GDA_LIBS) \
-
---- a/plugins/gdict/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/gdict/Makefile.in	2014-09-06 15:04:37.888425183 +0200
-@@ -423,7 +423,8 @@
- @GDICT_BUILTIN_FALSE@@TOOLKIT_GTK_TRUE@plugindir = $(ABIWORD_PLUGINSDIR)
- @GDICT_BUILTIN_FALSE@@TOOLKIT_GTK_TRUE@plugin_LTLIBRARIES = gdict.la
- @TOOLKIT_GTK_TRUE@gdict_la_LIBADD = \
--@TOOLKIT_GTK_TRUE@	unix/libunix.la
-+@TOOLKIT_GTK_TRUE@	unix/libunix.la \
-+@TOOLKIT_GTK_TRUE@	@top_builddir@/src/libabiword-2.8.la
- 
- @TOOLKIT_GTK_TRUE@gdict_la_LDFLAGS = \
- @TOOLKIT_GTK_TRUE@	$(GDICT_LIBS) \
-
---- a/plugins/gimp/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/gimp/Makefile.in	2014-09-06 15:04:47.380425494 +0200
-@@ -425,7 +425,8 @@
- @GIMP_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @GIMP_BUILTIN_FALSE@plugin_LTLIBRARIES = gimp.la
- gimp_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- gimp_la_LDFLAGS = \
- 	$(GIMP_LIBS) \
-
---- a/plugins/goffice/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/goffice/Makefile.in	2014-09-06 15:04:57.660425830 +0200
-@@ -419,7 +419,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = goffice.la
- goffice_la_LIBADD = \
--	unix/libunix.la
-+	unix/libunix.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- goffice_la_LDFLAGS = \
- 	$(GOFFICE_LIBS) \
-
---- a/plugins/google/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/google/Makefile.in	2014-09-06 15:05:06.852426131 +0200
-@@ -425,7 +425,8 @@
- @GOOGLE_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @GOOGLE_BUILTIN_FALSE@plugin_LTLIBRARIES = google.la
- google_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- google_la_LDFLAGS = \
- 	$(GOOGLE_LIBS) \
-
---- a/plugins/grammar/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/grammar/Makefile.in	2014-09-06 15:05:19.840426556 +0200
-@@ -424,7 +424,8 @@
- plugin_LTLIBRARIES = grammar.la
- grammar_la_LIBADD = \
- 	linkgrammarwrap/liblinkgrammarwrap.la \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- grammar_la_LDFLAGS = \
- 	$(GRAMMAR_LIBS) \
-
---- a/plugins/hancom/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/hancom/Makefile.in	2014-09-06 15:05:29.684426879 +0200
-@@ -425,7 +425,8 @@
- @HANCOM_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @HANCOM_BUILTIN_FALSE@plugin_LTLIBRARIES = hancom.la
- hancom_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- hancom_la_LDFLAGS = \
- 	$(HANCOM_LIBS) \
-
---- a/plugins/hrtext/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/hrtext/Makefile.in	2014-09-06 15:05:41.244427257 +0200
-@@ -425,7 +425,8 @@
- @HRTEXT_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @HRTEXT_BUILTIN_FALSE@plugin_LTLIBRARIES = hrtext.la
- hrtext_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- hrtext_la_LDFLAGS = \
- 	$(HRTEXT_LIBS) \
-
---- a/plugins/iscii/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/iscii/Makefile.in	2014-09-06 15:05:52.660427631 +0200
-@@ -425,7 +425,8 @@
- @ISCII_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @ISCII_BUILTIN_FALSE@plugin_LTLIBRARIES = iscii.la
- iscii_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- iscii_la_LDFLAGS = \
- 	$(ISCII_LIBS) \
-
---- a/plugins/kword/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/kword/Makefile.in	2014-09-06 15:06:01.260427912 +0200
-@@ -425,7 +425,8 @@
- @KWORD_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @KWORD_BUILTIN_FALSE@plugin_LTLIBRARIES = kword.la
- kword_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- kword_la_LDFLAGS = \
- 	$(KWORD_LIBS) \
-
---- a/plugins/latex/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/latex/Makefile.in	2014-09-06 15:06:13.212428304 +0200
-@@ -426,7 +426,8 @@
- @LATEX_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @LATEX_BUILTIN_FALSE@plugin_LTLIBRARIES = latex.la
- latex_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- latex_la_LDFLAGS = \
- 	$(LATEX_LIBS) \
-
---- a/plugins/loadbindings/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/loadbindings/Makefile.in	2014-09-06 15:06:27.340428766 +0200
-@@ -427,7 +427,8 @@
- @LOADBINDINGS_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @LOADBINDINGS_BUILTIN_FALSE@plugin_LTLIBRARIES = loadbindings.la
- loadbindings_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- loadbindings_la_LDFLAGS = \
- 	$(LOADBINDINGS_LIBS) \
-
---- a/plugins/mathview/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/mathview/Makefile.in	2014-09-06 15:06:35.428429031 +0200
-@@ -423,7 +423,8 @@
- plugin_LTLIBRARIES = mathview.la
- mathview_la_LIBADD = \
- 	itex2mml/libitex2mml.la \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- mathview_la_LDFLAGS = \
- 	$(MATHVIEW_LIBS) \
-
---- a/plugins/mht/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/mht/Makefile.in	2014-09-06 15:06:47.516429427 +0200
-@@ -422,7 +422,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = mht.la
- mht_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- mht_la_LDFLAGS = \
- 	$(MHT_LIBS) \
-
---- a/plugins/mif/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/mif/Makefile.in	2014-09-06 15:07:03.496429950 +0200
-@@ -425,7 +425,8 @@
- @MIF_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @MIF_BUILTIN_FALSE@plugin_LTLIBRARIES = mif.la
- mif_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- mif_la_LDFLAGS = \
- 	$(MIF_LIBS) \
-
---- a/plugins/mswrite/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/mswrite/Makefile.in	2014-09-06 15:07:15.700430349 +0200
-@@ -425,7 +425,8 @@
- @MSWRITE_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @MSWRITE_BUILTIN_FALSE@plugin_LTLIBRARIES = mswrite.la
- mswrite_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- mswrite_la_LDFLAGS = \
- 	$(MSWRITE_LIBS) \
-
---- a/plugins/opendocument/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/opendocument/Makefile.in	2014-09-06 15:07:26.668430709 +0200
-@@ -430,7 +430,8 @@
- opendocument_la_LIBADD = \
- 	common/libcommon.la \
- 	exp/libexp.la \
--	imp/libimp.la
-+	imp/libimp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- opendocument_la_LDFLAGS = \
- 	$(OPENDOCUMENT_LIBS) \
-
---- a/plugins/openwriter/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/openwriter/Makefile.in	2014-09-06 15:07:40.272431154 +0200
-@@ -426,7 +426,8 @@
- @OPENWRITER_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @OPENWRITER_BUILTIN_FALSE@plugin_LTLIBRARIES = openwriter.la
- openwriter_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- openwriter_la_LDFLAGS = \
- 	$(OPENWRITER_LIBS) \
-
---- a/plugins/openxml/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/openxml/Makefile.in	2014-09-06 15:08:44.312433251 +0200
-@@ -428,7 +428,8 @@
- openxml_la_LIBADD = \
- 	common/libcommon.la \
- 	imp/libimp.la \
--	exp/libexp.la
-+	exp/libexp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- openxml_la_LDFLAGS = \
- 	$(OPENXML_LIBS) \
-
---- a/plugins/opml/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/opml/Makefile.in	2014-09-06 15:08:58.424433713 +0200
-@@ -425,7 +425,8 @@
- @OPML_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @OPML_BUILTIN_FALSE@plugin_LTLIBRARIES = opml.la
- opml_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- opml_la_LDFLAGS = \
- 	$(OPML_LIBS) \
-
---- a/plugins/ots/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/ots/Makefile.in	2014-09-06 15:09:08.164434031 +0200
-@@ -419,7 +419,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = ots.la
- ots_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- ots_la_LDFLAGS = \
- 	$(OTS_LIBS) \
-
---- a/plugins/paint/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/paint/Makefile.in	2014-09-06 15:09:38.912435038 +0200
-@@ -426,7 +426,8 @@
- @PAINT_BUILTIN_FALSE@plugin_LTLIBRARIES = paint.la
- paint_la_LIBADD = \
- 	@PLATFORM@/lib@PLATFORM@.la \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- paint_la_LDFLAGS = \
- 	$(PAINT_LIBS) \
-
---- a/plugins/passepartout/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/passepartout/Makefile.in	2014-09-06 15:09:46.744435295 +0200
-@@ -427,7 +427,8 @@
- @PASSEPARTOUT_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @PASSEPARTOUT_BUILTIN_FALSE@plugin_LTLIBRARIES = passepartout.la
- passepartout_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- passepartout_la_LDFLAGS = \
- 	$(PASSEPARTOUT_LIBS) \
-
---- a/plugins/pdb/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/pdb/Makefile.in	2014-09-06 15:09:54.484435548 +0200
-@@ -425,7 +425,8 @@
- @PDB_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @PDB_BUILTIN_FALSE@plugin_LTLIBRARIES = pdb.la
- pdb_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- pdb_la_LDFLAGS = \
- 	$(PDB_LIBS) \
-
---- a/plugins/pdf/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/pdf/Makefile.in	2014-09-06 15:10:04.444435874 +0200
-@@ -425,7 +425,8 @@
- @PDF_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @PDF_BUILTIN_FALSE@plugin_LTLIBRARIES = pdf.la
- pdf_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- pdf_la_LDFLAGS = \
- 	$(PDF_LIBS) \
-
---- a/plugins/presentation/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/presentation/Makefile.in	2014-09-06 15:10:13.112436158 +0200
-@@ -427,7 +427,8 @@
- @PRESENTATION_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @PRESENTATION_BUILTIN_FALSE@plugin_LTLIBRARIES = presentation.la
- presentation_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- presentation_la_LDFLAGS = \
- 	$(PRESENTATION_LIBS) \
-
---- a/plugins/psion/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/psion/Makefile.in	2014-09-06 15:10:22.176436455 +0200
-@@ -421,7 +421,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = psion.la
- psion_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- psion_la_LDFLAGS = \
- 	$(PSION_LIBS) \
-
---- a/plugins/rsvg/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/rsvg/Makefile.in	2014-09-06 15:10:37.632436961 +0200
-@@ -425,7 +425,8 @@
- plugin_LTLIBRARIES = rsvg.la
- rsvg_la_LIBADD = \
- 	xp/libxp.la \
--	$(RSVG_LIBS) $(PNG_LIBS)
-+	$(RSVG_LIBS) $(PNG_LIBS) \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- rsvg_la_LDFLAGS = \
- 	-avoid-version \
-
---- a/plugins/s5/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/s5/Makefile.in	2014-09-06 15:10:46.652437256 +0200
-@@ -425,7 +425,8 @@
- @S5_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @S5_BUILTIN_FALSE@plugin_LTLIBRARIES = s5.la
- s5_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- s5_la_LDFLAGS = \
- 	$(S5_LIBS) \
-
---- a/plugins/sdw/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/sdw/Makefile.in	2014-09-06 15:10:58.072437630 +0200
-@@ -425,7 +425,8 @@
- @SDW_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @SDW_BUILTIN_FALSE@plugin_LTLIBRARIES = sdw.la
- sdw_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- sdw_la_LDFLAGS = \
- 	$(SDW_LIBS) \
-
---- a/plugins/t602/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/t602/Makefile.in	2014-09-06 15:11:06.224437897 +0200
-@@ -425,7 +425,8 @@
- @T602_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @T602_BUILTIN_FALSE@plugin_LTLIBRARIES = t602.la
- t602_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- t602_la_LDFLAGS = \
- 	$(T602_LIBS) \
-
---- a/plugins/urldict/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/urldict/Makefile.in	2014-09-06 15:11:14.404438165 +0200
-@@ -425,7 +425,8 @@
- @URLDICT_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @URLDICT_BUILTIN_FALSE@plugin_LTLIBRARIES = urldict.la
- urldict_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- urldict_la_LDFLAGS = \
- 	$(URLDICT_LIBS) \
-
---- a/plugins/wikipedia/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/wikipedia/Makefile.in	2014-09-06 15:11:22.064438415 +0200
-@@ -425,7 +425,8 @@
- @WIKIPEDIA_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @WIKIPEDIA_BUILTIN_FALSE@plugin_LTLIBRARIES = wikipedia.la
- wikipedia_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- wikipedia_la_LDFLAGS = \
- 	$(WIKIPEDIA_LIBS) \
-
---- a/plugins/wmf/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/wmf/Makefile.in	2014-09-06 15:11:31.348438719 +0200
-@@ -422,7 +422,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = wmf.la
- wmf_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- wmf_la_LDFLAGS = \
- 	$(WMF_LIBS) \
-
---- a/plugins/wml/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/wml/Makefile.in	2014-09-06 15:11:40.168439008 +0200
-@@ -425,7 +425,8 @@
- @WML_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @WML_BUILTIN_FALSE@plugin_LTLIBRARIES = wml.la
- wml_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- wml_la_LDFLAGS = \
- 	$(WML_LIBS) \
-
---- a/plugins/wordperfect/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/wordperfect/Makefile.in	2014-09-06 15:11:50.336439341 +0200
-@@ -423,7 +423,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = wordperfect.la
- wordperfect_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- wordperfect_la_LDFLAGS = \
- 	$(WORDPERFECT_LIBS) \
-
---- a/plugins/wpg/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/wpg/Makefile.in	2014-09-06 15:12:11.328440028 +0200
-@@ -422,7 +422,8 @@
- plugindir = $(ABIWORD_PLUGINSDIR)
- plugin_LTLIBRARIES = wpg.la
- wpg_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- wpg_la_LDFLAGS = \
- 	$(WPG_LIBS) \
-
---- a/plugins/xslfo/Makefile.in	2014-09-06 11:25:35.000000000 +0200
-+++ b/plugins/xslfo/Makefile.in	2014-09-06 15:12:44.984441130 +0200
-@@ -425,7 +425,8 @@
- @XSLFO_BUILTIN_FALSE@plugindir = $(ABIWORD_PLUGINSDIR)
- @XSLFO_BUILTIN_FALSE@plugin_LTLIBRARIES = xslfo.la
- xslfo_la_LIBADD = \
--	xp/libxp.la
-+	xp/libxp.la \
-+	@top_builddir@/src/libabiword-2.8.la
- 
- xslfo_la_LDFLAGS = \
- 	$(XSLFO_LIBS) \
diff --git a/gnu/packages/patches/abiword-no-include-glib-internal-headers.patch b/gnu/packages/patches/abiword-no-include-glib-internal-headers.patch
deleted file mode 100644
index 60a74920fb..0000000000
--- a/gnu/packages/patches/abiword-no-include-glib-internal-headers.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-Include glib.h instead of an internal header.
-
---- a/goffice-bits/goffice/app/goffice-app.h	2007-01-17 00:17:27.000000000 +0100
-+++ b/goffice-bits/goffice/app/goffice-app.h	2014-09-05 19:02:59.402064713 +0200
-@@ -22,7 +22,7 @@
- #ifndef GOFFICE_APP_H
- #define GOFFICE_APP_H
- 
--#include <glib/gmacros.h>
-+#include <glib.h>
- 
- G_BEGIN_DECLS
- 
diff --git a/gnu/packages/patches/abiword-pass-no-undefined-to-linker.patch b/gnu/packages/patches/abiword-pass-no-undefined-to-linker.patch
deleted file mode 100644
index a17d465edb..0000000000
--- a/gnu/packages/patches/abiword-pass-no-undefined-to-linker.patch
+++ /dev/null
@@ -1,608 +0,0 @@
-gcc/g++ chokes on --no-undefined, so instead pass it directly to the linker.
-
---- a/plugins/loadbindings/Makefile.in	2010-06-13 23:17:48.000000000 +0200
-+++ b/plugins/loadbindings/Makefile.in	2014-09-06 11:03:21.151951221 +0200
-@@ -433,7 +433,7 @@
- 	$(LOADBINDINGS_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- loadbindings_la_SOURCES = 
- nodist_EXTRA_loadbindings_la_SOURCES = dummy.cpp
-
---- a/plugins/pdf/Makefile.in	2010-06-13 23:17:53.000000000 +0200
-+++ b/plugins/pdf/Makefile.in	2014-09-06 11:03:21.207951223 +0200
-@@ -431,7 +431,7 @@
- 	$(PDF_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- pdf_la_SOURCES = 
- nodist_EXTRA_pdf_la_SOURCES = dummy.cpp
-
---- a/plugins/xslfo/Makefile.in	2010-06-13 23:17:55.000000000 +0200
-+++ b/plugins/xslfo/Makefile.in	2014-09-06 11:03:21.227951224 +0200
-@@ -431,7 +431,7 @@
- 	$(XSLFO_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- xslfo_la_SOURCES = 
- nodist_EXTRA_xslfo_la_SOURCES = dummy.cpp
-
---- a/plugins/gda/Makefile.in	2010-06-13 23:17:45.000000000 +0200
-+++ b/plugins/gda/Makefile.in	2014-09-06 11:03:21.251951225 +0200
-@@ -425,7 +425,7 @@
- 	$(GDA_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- gda_la_SOURCES = 
- EXTRA_DIST = \
-
---- a/plugins/wikipedia/Makefile.in	2010-06-13 23:17:54.000000000 +0200
-+++ b/plugins/wikipedia/Makefile.in	2014-09-06 11:03:21.271951225 +0200
-@@ -431,7 +431,7 @@
- 	$(WIKIPEDIA_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- wikipedia_la_SOURCES = 
- nodist_EXTRA_wikipedia_la_SOURCES = dummy.cpp
-
---- a/plugins/collab/Makefile.in	2010-06-13 23:17:41.000000000 +0200
-+++ b/plugins/collab/Makefile.in	2014-09-06 11:03:21.291951226 +0200
-@@ -435,7 +435,7 @@
- @TOOLKIT_COCOA_FALSE@	$(SYSTEM_LIBS) \
- @TOOLKIT_COCOA_FALSE@	-avoid-version \
- @TOOLKIT_COCOA_FALSE@	-module \
--@TOOLKIT_COCOA_FALSE@	-no-undefined
-+@TOOLKIT_COCOA_FALSE@	-Wl,--no-undefined
- 
- @TOOLKIT_COCOA_FALSE@collab_la_SOURCES = 
- @TOOLKIT_COCOA_FALSE@nodist_EXTRA_collab_la_SOURCES = dummy.cpp
-
---- a/plugins/paint/Makefile.in	2010-06-13 23:17:52.000000000 +0200
-+++ b/plugins/paint/Makefile.in	2014-09-06 11:03:21.315951227 +0200
-@@ -432,7 +432,7 @@
- 	$(PAINT_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- paint_la_SOURCES = 
- nodist_EXTRA_paint_la_SOURCES = dummy.cpp
-
---- a/plugins/garble/Makefile.in	2010-06-13 23:17:45.000000000 +0200
-+++ b/plugins/garble/Makefile.in	2014-09-06 11:03:21.335951227 +0200
-@@ -433,7 +433,7 @@
- @TOOLKIT_COCOA_FALSE@	$(GARBLE_LIBS) \
- @TOOLKIT_COCOA_FALSE@	-avoid-version \
- @TOOLKIT_COCOA_FALSE@	-module \
--@TOOLKIT_COCOA_FALSE@	-no-undefined
-+@TOOLKIT_COCOA_FALSE@	-Wl,--no-undefined
- 
- @TOOLKIT_COCOA_FALSE@garble_la_SOURCES = 
- @TOOLKIT_COCOA_FALSE@nodist_EXTRA_garble_la_SOURCES = dummy.cpp
-
---- a/plugins/latex/Makefile.in	2010-06-13 23:17:48.000000000 +0200
-+++ b/plugins/latex/Makefile.in	2014-09-06 11:03:21.359951228 +0200
-@@ -432,7 +432,7 @@
- 	$(LATEX_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- latex_la_SOURCES = 
- nodist_EXTRA_latex_la_SOURCES = dummy.cpp
-
---- a/plugins/mht/Makefile.in	2010-06-13 23:17:49.000000000 +0200
-+++ b/plugins/mht/Makefile.in	2014-09-06 11:03:21.379951229 +0200
-@@ -428,7 +428,7 @@
- 	$(MHT_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- mht_la_SOURCES = 
- nodist_EXTRA_mht_la_SOURCES = dummy.cpp
-
---- a/plugins/google/Makefile.in	2010-06-13 23:17:46.000000000 +0200
-+++ b/plugins/google/Makefile.in	2014-09-06 11:03:21.399951230 +0200
-@@ -431,7 +431,7 @@
- 	$(GOOGLE_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- google_la_SOURCES = 
- nodist_EXTRA_google_la_SOURCES = dummy.cpp
-
---- a/plugins/babelfish/Makefile.in	2010-06-13 23:17:40.000000000 +0200
-+++ b/plugins/babelfish/Makefile.in	2014-09-06 11:03:21.419951230 +0200
-@@ -431,7 +431,7 @@
- 	$(BABELFISH_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- babelfish_la_SOURCES = 
- nodist_EXTRA_babelfish_la_SOURCES = dummy.cpp
-
---- a/plugins/opendocument/Makefile.in	2010-06-13 23:17:50.000000000 +0200
-+++ b/plugins/opendocument/Makefile.in	2014-09-06 11:03:21.443951231 +0200
-@@ -436,7 +436,7 @@
- 	$(OPENDOCUMENT_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- opendocument_la_SOURCES = 
- 
---- a/plugins/opml/Makefile.in	2010-06-13 23:17:51.000000000 +0200
-+++ b/plugins/opml/Makefile.in	2014-09-06 11:03:21.463951232 +0200
-@@ -431,7 +431,7 @@
- 	$(OPML_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- opml_la_SOURCES = 
- nodist_EXTRA_opml_la_SOURCES = dummy.cpp
-
---- a/plugins/gimp/Makefile.in	2010-06-13 23:17:46.000000000 +0200
-+++ b/plugins/gimp/Makefile.in	2014-09-06 11:03:21.483951232 +0200
-@@ -431,7 +431,7 @@
- 	$(GIMP_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- gimp_la_SOURCES = 
- nodist_EXTRA_gimp_la_SOURCES = dummy.cpp
-
---- a/plugins/mswrite/Makefile.in	2010-06-13 23:17:49.000000000 +0200
-+++ b/plugins/mswrite/Makefile.in	2014-09-06 11:03:21.507951233 +0200
-@@ -431,7 +431,7 @@
- 	$(MSWRITE_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- mswrite_la_SOURCES = 
- nodist_EXTRA_mswrite_la_SOURCES = dummy.cpp
-
---- a/plugins/wordperfect/Makefile.in	2010-06-13 23:17:55.000000000 +0200
-+++ b/plugins/wordperfect/Makefile.in	2014-09-06 11:03:21.527951234 +0200
-@@ -429,7 +429,7 @@
- 	$(WORDPERFECT_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- wordperfect_la_SOURCES = 
- nodist_EXTRA_wordperfect_la_SOURCES = dummy.cpp
-
---- a/plugins/pdb/Makefile.in	2010-06-13 23:17:53.000000000 +0200
-+++ b/plugins/pdb/Makefile.in	2014-09-06 11:03:21.547951234 +0200
-@@ -431,7 +431,7 @@
- 	$(PDB_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- pdb_la_SOURCES = 
- nodist_EXTRA_pdb_la_SOURCES = dummy.cpp
-
---- a/plugins/ots/Makefile.in	2010-06-13 23:17:52.000000000 +0200
-+++ b/plugins/ots/Makefile.in	2014-09-06 11:03:21.571951235 +0200
-@@ -425,7 +425,7 @@
- 	$(OTS_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- ots_la_SOURCES = 
- EXTRA_DIST = \
-
---- a/plugins/wml/Makefile.in	2010-06-13 23:17:55.000000000 +0200
-+++ b/plugins/wml/Makefile.in	2014-09-06 11:03:21.591951236 +0200
-@@ -431,7 +431,7 @@
- 	$(WML_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- wml_la_SOURCES = 
- nodist_EXTRA_wml_la_SOURCES = dummy.cpp
-
---- a/plugins/bmp/Makefile.in	2010-06-13 23:17:40.000000000 +0200
-+++ b/plugins/bmp/Makefile.in	2014-09-06 11:03:21.615951237 +0200
-@@ -431,7 +431,7 @@
- 	$(BMP_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- bmp_la_SOURCES = 
- nodist_EXTRA_bmp_la_SOURCES = dummy.cpp
-
---- a/plugins/applix/Makefile.in	2010-06-13 23:17:40.000000000 +0200
-+++ b/plugins/applix/Makefile.in	2014-09-06 11:03:21.635951237 +0200
-@@ -431,7 +431,7 @@
- 	$(APPLIX_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- applix_la_SOURCES = 
- 
---- a/plugins/iscii/Makefile.in	2010-06-13 23:17:47.000000000 +0200
-+++ b/plugins/iscii/Makefile.in	2014-09-06 11:03:21.659951238 +0200
-@@ -431,7 +431,7 @@
- 	$(ISCII_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- iscii_la_SOURCES = 
- nodist_EXTRA_iscii_la_SOURCES = dummy.cpp
-
---- a/plugins/gdict/Makefile.in	2010-06-13 23:17:46.000000000 +0200
-+++ b/plugins/gdict/Makefile.in	2014-09-06 11:03:21.679951239 +0200
-@@ -429,7 +429,7 @@
- @TOOLKIT_GTK_TRUE@	$(GDICT_LIBS) \
- @TOOLKIT_GTK_TRUE@	-avoid-version \
- @TOOLKIT_GTK_TRUE@	-module \
--@TOOLKIT_GTK_TRUE@	-no-undefined
-+@TOOLKIT_GTK_TRUE@	-Wl,--no-undefined
- 
- @TOOLKIT_GTK_TRUE@gdict_la_SOURCES = 
- @TOOLKIT_GTK_TRUE@EXTRA_DIST = \
-
---- a/plugins/openwriter/Makefile.in	2010-06-13 23:17:50.000000000 +0200
-+++ b/plugins/openwriter/Makefile.in	2014-09-06 11:03:21.699951239 +0200
-@@ -432,7 +432,7 @@
- 	$(OPENWRITER_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- openwriter_la_SOURCES = 
- nodist_EXTRA_openwriter_la_SOURCES = dummy.cpp
-
---- a/plugins/sdw/Makefile.in	2010-06-13 23:17:54.000000000 +0200
-+++ b/plugins/sdw/Makefile.in	2014-09-06 11:03:21.723951240 +0200
-@@ -431,7 +431,7 @@
- 	$(SDW_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- sdw_la_SOURCES = 
- nodist_EXTRA_sdw_la_SOURCES = dummy.cpp
-
---- a/plugins/grammar/Makefile.in	2010-06-13 23:17:47.000000000 +0200
-+++ b/plugins/grammar/Makefile.in	2014-09-06 11:03:21.747951241 +0200
-@@ -430,7 +430,7 @@
- 	$(GRAMMAR_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- nodist_EXTRA_grammar_la_SOURCES = dummy.cpp
- grammar_la_SOURCES = 
-
---- a/plugins/urldict/Makefile.in	2010-06-13 23:17:54.000000000 +0200
-+++ b/plugins/urldict/Makefile.in	2014-09-06 11:03:21.779951242 +0200
-@@ -431,7 +431,7 @@
- 	$(URLDICT_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- urldict_la_SOURCES = 
- nodist_EXTRA_urldict_la_SOURCES = dummy.cpp
-
---- a/plugins/wmf/Makefile.in	2010-06-13 23:17:55.000000000 +0200
-+++ b/plugins/wmf/Makefile.in	2014-09-06 11:03:21.799951243 +0200
-@@ -428,7 +428,7 @@
- 	$(WMF_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- wmf_la_SOURCES = 
- nodist_EXTRA_wmf_la_SOURCES = dummy.cpp
-
---- a/plugins/mif/Makefile.in	2010-06-13 23:17:49.000000000 +0200
-+++ b/plugins/mif/Makefile.in	2014-09-06 11:03:21.819951243 +0200
-@@ -431,7 +431,7 @@
- 	$(MIF_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- mif_la_SOURCES = 
- nodist_EXTRA_mif_la_SOURCES = dummy.cpp
-
---- a/plugins/eml/Makefile.in	2010-06-13 23:17:45.000000000 +0200
-+++ b/plugins/eml/Makefile.in	2014-09-06 11:03:21.843951244 +0200
-@@ -431,7 +431,7 @@
- 	$(EML_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- eml_la_SOURCES = 
- nodist_EXTRA_eml_la_SOURCES = dummy.cpp
-
---- a/plugins/openxml/Makefile.in	2010-06-13 23:17:51.000000000 +0200
-+++ b/plugins/openxml/Makefile.in	2014-09-06 11:03:21.863951245 +0200
-@@ -434,7 +434,7 @@
- 	$(OPENXML_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- openxml_la_SOURCES = 
- nodist_EXTRA_openxml_la_SOURCES = dummy.cpp
-
---- a/plugins/goffice/Makefile.in	2010-06-13 23:17:46.000000000 +0200
-+++ b/plugins/goffice/Makefile.in	2014-09-06 11:03:21.883951245 +0200
-@@ -425,7 +425,7 @@
- 	$(GOFFICE_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- goffice_la_SOURCES = 
- EXTRA_DIST = \
-
---- a/plugins/passepartout/Makefile.in	2010-06-13 23:17:52.000000000 +0200
-+++ b/plugins/passepartout/Makefile.in	2014-09-06 11:03:21.907951246 +0200
-@@ -433,7 +433,7 @@
- 	$(PASSEPARTOUT_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- passepartout_la_SOURCES = 
- nodist_EXTRA_passepartout_la_SOURCES = dummy.cpp
-
---- a/plugins/clarisworks/Makefile.in	2010-06-13 23:17:41.000000000 +0200
-+++ b/plugins/clarisworks/Makefile.in	2014-09-06 11:03:21.927951247 +0200
-@@ -433,7 +433,7 @@
- 	$(CLARISWORKS_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- clarisworks_la_SOURCES = 
- nodist_EXTRA_clarisworks_la_SOURCES = dummy.cpp
-
---- a/plugins/command/Makefile.in	2010-06-13 23:17:44.000000000 +0200
-+++ b/plugins/command/Makefile.in	2014-09-06 11:03:21.947951247 +0200
-@@ -426,7 +426,7 @@
- @TOOLKIT_COCOA_FALSE@	$(COMMAND_LIBS) \
- @TOOLKIT_COCOA_FALSE@	-avoid-version \
- @TOOLKIT_COCOA_FALSE@	-module \
--@TOOLKIT_COCOA_FALSE@	-no-undefined
-+@TOOLKIT_COCOA_FALSE@	-Wl,--no-undefined
- 
- @TOOLKIT_COCOA_FALSE@command_la_SOURCES = 
- all: all-recursive
-
---- a/plugins/presentation/Makefile.in	2010-06-13 23:17:53.000000000 +0200
-+++ b/plugins/presentation/Makefile.in	2014-09-06 11:03:21.971951248 +0200
-@@ -433,7 +433,7 @@
- 	$(PRESENTATION_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- presentation_la_SOURCES = 
- nodist_EXTRA_presentation_la_SOURCES = dummy.cpp
-
---- a/plugins/psion/Makefile.in	2010-06-13 23:17:53.000000000 +0200
-+++ b/plugins/psion/Makefile.in	2014-09-06 11:03:21.991951249 +0200
-@@ -427,7 +427,7 @@
- 	$(PSION_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- psion_la_SOURCES = 
- EXTRA_DIST = \
-
---- a/plugins/rsvg/Makefile.in	2010-06-13 23:17:53.000000000 +0200
-+++ b/plugins/rsvg/Makefile.in	2014-09-06 11:03:22.011951250 +0200
-@@ -430,7 +430,7 @@
- rsvg_la_LDFLAGS = \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- rsvg_la_SOURCES = 
- nodist_EXTRA_rsvg_la_SOURCES = dummy.cpp
-
---- a/plugins/wpg/Makefile.in	2010-06-13 23:17:55.000000000 +0200
-+++ b/plugins/wpg/Makefile.in	2014-09-06 11:03:22.035951250 +0200
-@@ -428,7 +428,7 @@
- 	$(WPG_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- wpg_la_SOURCES = 
- nodist_EXTRA_wpg_la_SOURCES = dummy.cpp
-
---- a/plugins/t602/Makefile.in	2010-06-13 23:17:54.000000000 +0200
-+++ b/plugins/t602/Makefile.in	2014-09-06 11:03:22.055951251 +0200
-@@ -431,7 +431,7 @@
- 	$(T602_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- t602_la_SOURCES = 
- nodist_EXTRA_t602_la_SOURCES = dummy.cpp
-
---- a/plugins/docbook/Makefile.in	2010-06-13 23:17:44.000000000 +0200
-+++ b/plugins/docbook/Makefile.in	2014-09-06 11:03:22.075951252 +0200
-@@ -431,7 +431,7 @@
- 	$(DOCBOOK_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- docbook_la_SOURCES = 
- nodist_EXTRA_docbook_la_SOURCES = dummy.cpp
-
---- a/plugins/hrtext/Makefile.in	2010-06-13 23:17:47.000000000 +0200
-+++ b/plugins/hrtext/Makefile.in	2014-09-06 11:03:22.099951252 +0200
-@@ -431,7 +431,7 @@
- 	$(HRTEXT_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- hrtext_la_SOURCES = 
- nodist_EXTRA_hrtext_la_SOURCES = dummy.cpp 
-
---- a/plugins/s5/Makefile.in	2010-06-13 23:17:54.000000000 +0200
-+++ b/plugins/s5/Makefile.in	2014-09-06 11:03:22.119951253 +0200
-@@ -431,7 +431,7 @@
- 	$(S5_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- s5_la_SOURCES = 
- nodist_EXTRA_s5_la_SOURCES = dummy.cpp
-
---- a/plugins/hancom/Makefile.in	2010-06-13 23:17:47.000000000 +0200
-+++ b/plugins/hancom/Makefile.in	2014-09-06 11:03:22.143951254 +0200
-@@ -431,7 +431,7 @@
- 	$(HANCOM_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- hancom_la_SOURCES = 
- nodist_EXTRA_hancom_la_SOURCES = dummy.cpp
-
---- a/plugins/aiksaurus/Makefile.in	2010-06-13 23:17:40.000000000 +0200
-+++ b/plugins/aiksaurus/Makefile.in	2014-09-06 11:03:22.163951255 +0200
-@@ -428,7 +428,7 @@
- 	$(AIKSAURUS_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- aiksaurus_la_SOURCES = 
- all: all-recursive
-
---- a/plugins/kword/Makefile.in	2010-06-13 23:17:48.000000000 +0200
-+++ b/plugins/kword/Makefile.in	2014-09-06 11:03:22.183951255 +0200
-@@ -431,7 +431,7 @@
- 	$(KWORD_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- kword_la_SOURCES = 
- nodist_EXTRA_kword_la_SOURCES = dummy.cpp
-
---- a/plugins/freetranslation/Makefile.in	2010-06-13 23:17:45.000000000 +0200
-+++ b/plugins/freetranslation/Makefile.in	2014-09-06 11:03:22.207951256 +0200
-@@ -433,7 +433,7 @@
- 	$(FREETRANSLATION_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- freetranslation_la_SOURCES = 
- nodist_EXTRA_freetranslation_la_SOURCES = dummy.cpp
-
---- a/plugins/mathview/Makefile.in	2010-06-13 23:17:48.000000000 +0200
-+++ b/plugins/mathview/Makefile.in	2014-09-06 11:03:22.227951257 +0200
-@@ -429,7 +429,7 @@
- 	$(MATHVIEW_LIBS) \
- 	-avoid-version \
- 	-module \
--	-no-undefined
-+	-Wl,--no-undefined
- 
- nodist_EXTRA_mathview_la_SOURCES = dummy.cpp
- mathview_la_SOURCES = 
-
---- a/src/Makefile.in	2014-09-06 08:42:45.000000000 +0200
-+++ b/src/Makefile.in	2014-09-06 11:17:48.287979611 +0200
-@@ -538,7 +538,7 @@
- 
- @TOOLKIT_COCOA_TRUE@AbiWord_LDFLAGS = \
- @TOOLKIT_COCOA_TRUE@	$(DEPS_LIBS) \
--@TOOLKIT_COCOA_TRUE@	--no-undefined \
-+@TOOLKIT_COCOA_TRUE@	-Wl,--no-undefined \
- @TOOLKIT_COCOA_TRUE@	-avoid-version \
- @TOOLKIT_COCOA_TRUE@	-export-dynamic \
- @TOOLKIT_COCOA_TRUE@	-headerpad_max_install_names 
-@@ -554,7 +554,7 @@
- 
- @TOOLKIT_COCOA_FALSE@abiword_LDFLAGS = \
- @TOOLKIT_COCOA_FALSE@	$(platform_ldflags) \
--@TOOLKIT_COCOA_FALSE@	--no-undefined      \
-+@TOOLKIT_COCOA_FALSE@	-Wl,--no-undefined      \
- @TOOLKIT_COCOA_FALSE@	-avoid-version      \
- @TOOLKIT_COCOA_FALSE@	-export-dynamic
- 
diff --git a/gnu/packages/patches/abiword-use-proper-png-api.patch b/gnu/packages/patches/abiword-use-proper-png-api.patch
deleted file mode 100644
index e8ce02899d..0000000000
--- a/gnu/packages/patches/abiword-use-proper-png-api.patch
+++ /dev/null
@@ -1,175 +0,0 @@
-Do not directly access the fields of png_struct and png_info.
-
---- a/plugins/mswrite/xp/ie_imp_MSWrite.cpp	2010-05-30 21:20:53.000000000 +0200
-+++ b/plugins/mswrite/xp/ie_imp_MSWrite.cpp	2014-09-07 06:58:04.162298089 +0200
-@@ -891,7 +891,7 @@
- 		info_ptr = png_create_info_struct (png_ptr);
- 		if (!info_ptr) goto err;
- 		
--		if (setjmp (png_ptr->jmpbuf) ) {
-+		if (setjmp (png_jmpbuf(png_ptr)) ) {
- 			png_destroy_write_struct (&png_ptr, &info_ptr);
- 			goto err;
- 		}
-
---- a/src/af/gr/win/gr_Win32Image.cpp	2009-07-08 19:33:53.000000000 +0200
-+++ b/src/af/gr/win/gr_Win32Image.cpp	2014-09-07 06:58:04.198298090 +0200
-@@ -148,7 +148,7 @@
- 	info_ptr = png_create_info_struct(png_ptr);
- 
- 	// libpng will longjmp back to here if a fatal error occurs
--	if (setjmp(png_ptr->jmpbuf))
-+	if (setjmp(png_jmpbuf(png_ptr)))
- 	{
- 		/* If we get here, we had a problem reading the file */
- 		png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
-@@ -547,7 +547,7 @@
- 	 * the normal method of doing things with libpng).  REQUIRED unless you
- 	 * set up your own error handlers in the png_create_read_struct() earlier.
- 	 */
--	if (setjmp(png_ptr->jmpbuf))
-+	if (setjmp(png_jmpbuf(png_ptr)))
- 	{
- 		/* Free all of the memory associated with the png_ptr and info_ptr */
- 		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
-
---- a/src/af/util/xp/ut_png.cpp	2008-02-24 04:33:07.000000000 +0100
-+++ b/src/af/util/xp/ut_png.cpp	2014-09-07 06:58:04.230298091 +0200
-@@ -71,7 +71,7 @@
- 	 * the normal method of doing things with libpng).  REQUIRED unless you
- 	 * set up your own error handlers in the png_create_read_struct() earlier.
- 	 */
--	if (setjmp(png_ptr->jmpbuf))
-+	if (setjmp(png_jmpbuf(png_ptr)))
- 	{
- 		/* Free all of the memory associated with the png_ptr and info_ptr */
- 		png_destroy_read_struct(&png_ptr, &info_ptr, static_cast<png_infopp>(NULL));
-
---- a/plugins/bmp/xp/ie_impGraphic_BMP.cpp	2009-06-25 06:02:06.000000000 +0200
-+++ b/plugins/bmp/xp/ie_impGraphic_BMP.cpp	2014-09-07 06:59:08.814300205 +0200
-@@ -313,7 +313,7 @@
- 	 * the normal method of doing things with libpng).  REQUIRED unless you
- 	 * set up your own error handlers in the png_create_read_struct() earlier.
- 	 */
--	if (setjmp(m_pPNG->jmpbuf))
-+	if (setjmp(png_jmpbuf(m_pPNG)))
- 	{
- 		/* Free all of the memory associated with the png_ptr and info_ptr */
- 		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
-@@ -332,7 +332,7 @@
- 	UT_Error IE_ImpGraphic_BMP::Convert_BMP_Pallet(UT_ByteBuf* pBB)
- 	{
- 		/* Reset error handling for libpng */
--		if (setjmp(m_pPNG->jmpbuf))
-+		if (setjmp(png_jmpbuf(m_pPNG)))
- 		{
- 			png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
- 			return UT_ERROR;
-@@ -372,7 +372,7 @@
- UT_Error IE_ImpGraphic_BMP::Convert_BMP(UT_ByteBuf* pBB)
- {
- 	/* Reset error handling for libpng */
--	if (setjmp(m_pPNG->jmpbuf))
-+	if (setjmp(png_jmpbuf(m_pPNG)))
- 	{
- 		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
- 		return UT_ERROR;
-
---- a/plugins/rsvg/xp/AbiRSVG.cpp	2009-06-25 06:02:06.000000000 +0200
-+++ b/plugins/rsvg/xp/AbiRSVG.cpp	2014-09-07 06:59:08.914300209 +0200
-@@ -145,7 +145,7 @@
- 				return error;
- 			}
- 		
--		if (setjmp(m_pPNG->jmpbuf))
-+		if (setjmp(png_jmpbuf(m_pPNG)))
- 			{
- 				g_object_unref(G_OBJECT(pixbuf));
- 				png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
-@@ -234,7 +234,7 @@
- 		 * the normal method of doing things with libpng).  REQUIRED unless you
- 		 * set up your own error handlers in the png_create_read_struct() earlier.
- 		 */
--		if (setjmp(m_pPNG->jmpbuf))
-+		if (setjmp(png_jmpbuf(m_pPNG)))
- 			{
- 				/* Free all of the memory associated with the png_ptr and info_ptr */
- 				png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
-
---- a/src/wp/impexp/win/ie_impGraphic_Win32Native.cpp	2009-07-07 18:50:18.000000000 +0200
-+++ b/src/wp/impexp/win/ie_impGraphic_Win32Native.cpp	2014-09-07 06:59:09.018300212 +0200
-@@ -501,7 +501,7 @@
-      * the normal method of doing things with libpng).  REQUIRED unless you
-      * set up your own error handlers in the png_create_read_struct() earlier.
-      */
--    if (setjmp(m_pPNG->jmpbuf))
-+    if (setjmp(png_jmpbuf(m_pPNG)))
- 	{
- 		/* Free all of the memory associated with the png_ptr and info_ptr */
- 		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
-@@ -520,7 +520,7 @@
- UT_Error IE_ImpGraphic_Win32Native::Convert_BMP_Palette(UT_ByteBuf* pBB)
- {
-     /* Reset error handling for libpng */
--    if (setjmp(m_pPNG->jmpbuf))
-+    if (setjmp(png_jmpbuf(m_pPNG)))
- 	{
- 		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
- 		return UT_ERROR;
-@@ -560,7 +560,7 @@
- UT_Error IE_ImpGraphic_Win32Native::Convert_BMP(UT_ByteBuf* pBB)
- {
-     /* Reset error handling for libpng */
--    if (setjmp(m_pPNG->jmpbuf))
-+    if (setjmp(png_jmpbuf(m_pPNG)))
- 	{
- 		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
- 		return UT_ERROR;
-
---- a/src/wp/impexp/gtk/ie_impGraphic_GdkPixbuf.cpp	2009-07-01 06:02:04.000000000 +0200
-+++ b/src/wp/impexp/gtk/ie_impGraphic_GdkPixbuf.cpp	2014-09-07 06:59:09.138300216 +0200
-@@ -185,7 +185,7 @@
- /** needed for the stejmp context */
- UT_Error IE_ImpGraphic_GdkPixbuf::_png_write(GdkPixbuf * pixbuf)
- {
--	if (setjmp(m_pPNG->jmpbuf))
-+	if (setjmp(png_jmpbuf(m_pPNG)))
- 	{
- 		DELETEP(m_pPngBB);
- 		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
-@@ -446,7 +446,7 @@
- 	 * the normal method of doing things with libpng).  REQUIRED unless you
- 	 * set up your own error handlers in the png_create_read_struct() earlier.
- 	 */
--	if (setjmp(m_pPNG->jmpbuf))
-+	if (setjmp(png_jmpbuf(m_pPNG)))
- 	{
- 		/* Free all of the memory associated with the png_ptr and info_ptr */
- 		png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
-
---- a/plugins/bmp/xp/ie_impGraphic_BMP.cpp	2014-09-07 07:03:02.000000000 +0200
-+++ b/plugins/bmp/xp/ie_impGraphic_BMP.cpp	2014-09-07 12:35:33.306961036 +0200
-@@ -191,7 +191,11 @@
- 
- 	/* Clean Up Memory Used */
- 		
--	FREEP(m_pPNGInfo->palette);
-+	
-+	png_colorp palette;
-+	int ignored_placeholder;
-+	png_get_PLTE(m_pPNG, m_pPNGInfo, &palette, &ignored_placeholder);
-+	FREEP(palette);
- 	DELETEP(pBB);
- 	png_destroy_write_struct(&m_pPNG, &m_pPNGInfo);
-    
---- a/plugins/garble/xp/abiword-garble-png.cpp	2009-09-05 17:34:44.000000000 +0200
-+++ b/plugins/garble/xp/abiword-garble-png.cpp	2014-09-08 00:15:04.508335153 +0200
-@@ -79,7 +79,7 @@
- 		png_set_strip_alpha( png_ptr );
- 		png_set_interlace_handling( png_ptr );
- 		png_set_bgr( png_ptr );
--		rowbytes = info_ptr->rowbytes;
-+		rowbytes = png_get_rowbytes( png_ptr, info_ptr );
- 		png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
- 	}
- 
diff --git a/gnu/packages/patches/asymptote-gsl2.patch b/gnu/packages/patches/asymptote-gsl2.patch
deleted file mode 100644
index 4f73d16d7f..0000000000
--- a/gnu/packages/patches/asymptote-gsl2.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 71ff9e769ba5d9995b367201f0d41b7a8dedab9d Mon Sep 17 00:00:00 2001
-From: John Bowman <bowman@ualberta.ca>
-Date: Sat, 14 Nov 2015 01:25:56 -0700
-Subject: [PATCH] Support GSL 2.0.
-
----
- gsl.cc | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/gsl.cc b/gsl.cc
-index b500557..0f81dc6 100644
---- a/gsl.cc
-+++ b/gsl.cc
-@@ -27,6 +27,7 @@
- #include <gsl/gsl_rng.h>
- #include <gsl/gsl_randist.h>
- #include <gsl/gsl_cdf.h>
-+#include <gsl/gsl_version.h>
- 
- #include "opsymbols.h"
- 
-@@ -1088,7 +1089,11 @@ void gen_rungsl_venv(venv &ve)
-   addGSLDOUBLE2Func<gsl_sf_ellint_F>(SYM(F));
-   addGSLDOUBLE2Func<gsl_sf_ellint_E>(SYM(E));
-   addGSLDOUBLE3Func<gsl_sf_ellint_P>(SYM(P),SYM(phi),SYM(k),SYM(n));
-+#if GSL_MAJOR_VERSION >= 2
-+  addGSLDOUBLE2Func<gsl_sf_ellint_D>(SYM(D),SYM(phi),SYM(k));
-+#else  
-   addGSLDOUBLE3Func<gsl_sf_ellint_D>(SYM(D),SYM(phi),SYM(k),SYM(n));
-+#endif  
-   addGSLDOUBLE2Func<gsl_sf_ellint_RC>(SYM(RC),SYM(x),SYM(y));
-   addGSLDOUBLE3Func<gsl_sf_ellint_RD>(SYM(RD),SYM(x),SYM(y),SYM(z));
-   addGSLDOUBLE3Func<gsl_sf_ellint_RF>(SYM(RF),SYM(x),SYM(y),SYM(z));
diff --git a/gnu/packages/patches/fltk-xfont-on-demand.patch b/gnu/packages/patches/fltk-xfont-on-demand.patch
new file mode 100644
index 0000000000..cdcdd9af05
--- /dev/null
+++ b/gnu/packages/patches/fltk-xfont-on-demand.patch
@@ -0,0 +1,45 @@
+Fixes undefined reference to `Fl_XFont_On_Demand::value()'.
+From <http://www.fltk.org/str.php?L3156+P0+S0+C0+I0+E0+V1+QOn_Demand>.
+
+Index: src/fl_font.cxx
+===================================================================
+--- fltk-1.3.3/src/fl_font.cxx	(revision 10503)
++++ fltk-1.3.3/src/fl_font.cxx	(revision 10504)
+@@ -55,6 +55,12 @@
+ #  include "fl_font_x.cxx"
+ #endif // WIN32
+ 
++#if ! (defined(WIN32) || defined(__APPLE__))
++XFontStruct *fl_X_core_font()
++{
++  return fl_xfont.value();
++}
++#endif
+ 
+ double fl_width(const char* c) {
+   if (c) return fl_width(c, (int) strlen(c));
+Index: src/gl_draw.cxx
+===================================================================
+--- fltk-1.3.3/src/gl_draw.cxx	(revision 10503)
++++ fltk-1.3.3/src/gl_draw.cxx	(revision 10504)
+@@ -81,7 +81,7 @@
+  * then sorting through them at draw time (for normal X rendering) to find which one can
+  * render the current glyph... But for now, just use the first font in the list for GL...
+  */
+-    XFontStruct *font = fl_xfont;
++    XFontStruct *font = fl_X_core_font();
+     int base = font->min_char_or_byte2;
+     int count = font->max_char_or_byte2-base+1;
+     fl_fontsize->listbase = glGenLists(256);
+Index: FL/x.H
+===================================================================
+--- fltk-1.3.3/FL/x.H	(revision 10503)
++++ fltk-1.3.3/FL/x.H	(revision 10504)
+@@ -132,6 +132,7 @@
+   XFontStruct *ptr;
+ };
+ extern FL_EXPORT Fl_XFont_On_Demand fl_xfont;
++extern FL_EXPORT XFontStruct* fl_X_core_font();
+ 
+ // this object contains all X-specific stuff about a window:
+ // Warning: this object is highly subject to change!  
diff --git a/gnu/packages/patches/fontforge-svg-modtime.patch b/gnu/packages/patches/fontforge-svg-modtime.patch
new file mode 100644
index 0000000000..fd960ae610
--- /dev/null
+++ b/gnu/packages/patches/fontforge-svg-modtime.patch
@@ -0,0 +1,35 @@
+Propagate source font modification time to svg during conversion.  Similar to
+what upstream commit 95a470e941d9a20fbdaca51334e8b6b9d93cfae4 did for TTF
+files.
+
+Submitted upstream at http://github.com/fontforge/fontforge/pull/2696
+
+--- a/fontforge/svg.c
++++ b/fontforge/svg.c
+@@ -27,7 +27,6 @@
+ #include "fontforgevw.h"
+ #include <unistd.h>
+ #include <math.h>
+-#include <time.h>
+ #include <locale.h>
+ #include <utype.h>
+ #include <chardata.h>
+@@ -62,7 +61,6 @@ static int svg_outfontheader(FILE *file, SplineFont *sf,int layer) {
+     BlueData bd;
+     char *hash, *hasv, ch;
+     int minu, maxu, i;
+-    time_t now;
+     const char *author = GetAuthor();
+ 
+     memset(&info,0,sizeof(info));
+@@ -78,9 +76,8 @@ static int svg_outfontheader(FILE *file, SplineFont *sf,int layer) {
+ 	fprintf( file, "\n-->\n" );
+     }
+     fprintf( file, "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\">\n" );
+-    time(&now);
+     fprintf( file, "<metadata>\nCreated by FontForge %d at %s",
+-	    FONTFORGE_VERSIONDATE_RAW, ctime(&now) );
++	    FONTFORGE_VERSIONDATE_RAW, ctime((time_t*)&sf->modificationtime) );
+     if ( author!=NULL )
+ 	fprintf(file," By %s\n", author);
+     else
diff --git a/gnu/packages/patches/fossil-test-fixes.patch b/gnu/packages/patches/fossil-test-fixes.patch
new file mode 100644
index 0000000000..e6c9f3dd74
--- /dev/null
+++ b/gnu/packages/patches/fossil-test-fixes.patch
@@ -0,0 +1,189 @@
+From upstream commit https://www.fossil-scm.org/fossil/info/19c216391a0ad79e
+
+--- fossil-src-1.34/test/file1.test
++++ fossil-src-1.34/test/file1.test
+@@ -15,10 +15,12 @@
+ #
+ ############################################################################
+ #
+ # File utilities
+ #
++
++repo_init
+ 
+ proc simplify-name {testname args} {
+   set i 1
+   foreach {path result} $args {
+     fossil test-simplify-name $path
+@@ -65,10 +67,13 @@
+ 
+ if {$::tcl_platform(os)=="Windows NT"} {
+   simplify-name 108 //?/a:/a/b a:/a/b //?/UNC/a/b //a/b //?/ {}
+   simplify-name 109 \\\\?\\a:\\a\\b a:/a/b \\\\?\\UNC\\a\\b //a/b \\\\?\\ {}
+ }
++
++# This is needed because we are now running outside of the Fossil checkout.
++file mkdir file1; cd file1
+ 
+ # Those directories are only needed for the testcase being able to "--chdir" to it.
+ file mkdir test1
+ file mkdir test1/test2
+
+From upstream commit https://www.fossil-scm.org/fossil/info/ad6de6383391bd4d
+ 
+--- fossil-src-1.34/test/utf.test
++++ fossil-src-1.34/test/utf.test
+@@ -39,26 +39,29 @@
+     test utf-check-$testname.$i {$::RESULT eq $result}
+     incr i
+   }
+ }
+ 
++unset -nocomplain enc
+ array set enc [list     \
+       0 binary          \
+       1 binary          \
+       2 unicode         \
+       3 unicode-reverse \
+ ]
+ 
++unset -nocomplain bom
+ array set bom [list                                         \
+       0 ""                                                  \
+       1 \xEF\xBB\xBF                                        \
+       2 [expr {$tcl_platform(byteOrder) eq "littleEndian" ? \
+             "\xFF\xFE" : "\xFE\xFF"}]                       \
+       3 [expr {$tcl_platform(byteOrder) eq "littleEndian" ? \
+             "\xFE\xFF" : "\xFF\xFE"}]                       \
+ ]
+ 
++unset -nocomplain data
+ array set data [list                          \
+       0 ""                                    \
+       1 \r                                    \
+       2 \n                                    \
+       3 \r\n                                  \
+@@ -239,10 +242,11 @@
+     178 \xF4\x90\x80\x80\r                    \
+     179 \xF4\x90\x80\x80\n                    \
+     180 \xF4\x90\x80\x80\r\n                  \
+ ]
+ 
++unset -nocomplain extraData
+ array set extraData [list                     \
+       0 ""                                    \
+       1 Z                                     \
+ ]
+
+Backport from upstream https://www.fossil-scm.org/fossil/info/60285f5876512817
+with additional non-zero exit in case of failures.
+
+--- fossil-src-1.34/test/merge6.test
++++ fossil-src-1.34/test/merge6.test
+@@ -62,6 +62,6 @@
+ fossil ls
+ 
+ test merge_multi-4 {[normalize_result] eq {f1
+ f2
+ f3
+-f4}}
++f4}} knownBug
+
+--- fossil-src-1.34/test/merge_renames.test
++++ fossil-src-1.34/test/merge_renames.test
+@@ -156,13 +156,13 @@
+ }
+ 
+ if {$deletes!=0} {
+     # failed
+     protOut "Error, the merge should not delete any file"
+-    test merge_renames-2 0
++    test merge_renames-3 0
+ } else {
+-    test merge_renames-2 1
++    test merge_renames-3 1
+ }
+ 
+ ######################################
+ #  Test 4                            #
+ #  Reported: Ticket [67176c3aa4]     #
+@@ -198,14 +198,14 @@
+ 
+ fossil ls
+ 
+ test merge_renames-5 {[normalize_result] eq {f1
+ f2
+-f3}}
++f3}} knownBug
+ 
+ ######################################
+ #
+ # Tests for troubles not specifically linked with renames but that I'd like to
+ # write:
+ #  [c26c63eb1b] - 'merge --backout' does not handle conflicts properly
+ #  [953031915f] - Lack of warning when overwriting extra files
+ #  [4df5f38f1e] - Troubles merging a file delete with a file change
+
+--- fossil-src-1.34/test/tester.tcl
++++ fossil-src-1.34/test/tester.tcl
+@@ -58,10 +58,18 @@
+   set VERBOSE 1
+   set argv [lreplace $argv $i $i]
+ } else {
+   set VERBOSE 0
+ }
++
++set i [lsearch $argv -strict]
++if {$i>=0} {
++  set STRICT 1
++  set argv [lreplace $argv $i $i]
++} else {
++  set STRICT 0
++}
+ 
+ if {[llength $argv]==0} {
+   foreach f [lsort [glob $testdir/*.test]] {
+     set base [file root [file tail $f]]
+     lappend argv $base
+@@ -327,20 +335,30 @@
+ }
+ 
+ # Perform a test
+ #
+ set test_count 0
+-proc test {name expr} {
++proc test {name expr {constraints ""}} {
+   global bad_test test_count
+   incr test_count
++  set knownBug [expr {"knownBug" in $constraints}]
+   set r [uplevel 1 [list expr $expr]]
+   if {$r} {
+-    protOut "test $name OK"
++    if {$knownBug && !$::STRICT} {
++      protOut "test $name OK (knownBug)?"
++    } else {
++      protOut "test $name OK"
++    }
+   } else {
+-    protOut "test $name FAILED!"
+-    lappend bad_test $name
+-    if {$::HALT} exit
++    if {$knownBug && !$::STRICT} {
++      protOut "test $name FAILED (knownBug)!"
++    } else {
++      protOut "test $name FAILED!"
++      if {$::VERBOSE} {protOut "RESULT: $RESULT"}
++      lappend bad_test $name
++      if {$::HALT} exit
++    }
+   }
+ }
+ set bad_test {}
+ 
+ # Return a random string N characters long.
+@@ -445,4 +455,5 @@
+ protOut "***** Final result: $nErr errors out of $test_count tests"
+ if {$nErr>0} {
+   protOut "***** Failures: $bad_test"
++  exit 1
+ }
diff --git a/gnu/packages/patches/icecat-CVE-2015-4477.patch b/gnu/packages/patches/icecat-CVE-2015-4477.patch
deleted file mode 100644
index c010c5ecec..0000000000
--- a/gnu/packages/patches/icecat-CVE-2015-4477.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/beae8783b8c2
-
-# HG changeset patch
-# User Paul Adenot <paul@paul.cx>
-# Date 1456422965 0
-# Node ID beae8783b8c2c672da12a95c70ae663cbd0d5016
-# Parent  3a606f8182c82480f8f350b622ab55a170ec1eb6
-Bug 1179484. r=roc
-
-MozReview-Commit-ID: HNaYLyMe3sM
-
-diff --git a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
---- a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
-+++ b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
-@@ -69,16 +69,20 @@ MediaStreamAudioDestinationNode::MediaSt
-               ChannelInterpretation::Speakers)
-   , mDOMStream(DOMAudioNodeMediaStream::CreateTrackUnionStream(GetOwner(),
-                                                                this))
- {
-   TrackUnionStream* tus = static_cast<TrackUnionStream*>(mDOMStream->GetStream());
-   MOZ_ASSERT(tus == mDOMStream->GetStream()->AsProcessedStream());
-   tus->SetTrackIDFilter(FilterAudioNodeStreamTrack);
- 
-+  if (aContext->Graph() != tus->Graph()) {
-+    return;
-+  }
-+
-   MediaStreamDestinationEngine* engine = new MediaStreamDestinationEngine(this, tus);
-   mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
-   mPort = tus->AllocateInputPort(mStream, 0);
- 
-   nsIDocument* doc = aContext->GetParentObject()->GetExtantDoc();
-   if (doc) {
-     mDOMStream->CombineWithPrincipal(doc->NodePrincipal());
-   }
-
diff --git a/gnu/packages/patches/icecat-CVE-2015-7207.patch b/gnu/packages/patches/icecat-CVE-2015-7207.patch
deleted file mode 100644
index db5fc6ce66..0000000000
--- a/gnu/packages/patches/icecat-CVE-2015-7207.patch
+++ /dev/null
@@ -1,1140 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/532544c91db7
-
-# HG changeset patch
-# User Dragana Damjanovic <dd.mozilla@gmail.com>
-# Date 1456962626 28800
-# Node ID 532544c91db7f13c39be1b7b7c4461cd03126e9c
-# Parent  f4220254d5bd0851a439467da39ba431e0ce2804
-Bug 1185256 - Save originURI to the history. r=bz ba=ritu
-
-MozReview-Commit-ID: Lvh9C84RQUc
-
-diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
---- a/docshell/base/nsDocShell.cpp
-+++ b/docshell/base/nsDocShell.cpp
-@@ -1020,16 +1020,17 @@ nsDocShell::DestroyChildren()
- //*****************************************************************************
- // nsDocShell::nsISupports
- //*****************************************************************************
- 
- NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
- NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
- 
- NS_INTERFACE_MAP_BEGIN(nsDocShell)
-+  NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38_2)
-   NS_INTERFACE_MAP_ENTRY(nsIDocShell_ESR38)
-   NS_INTERFACE_MAP_ENTRY(nsIDocShell)
-   NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
-   NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
-   NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
-   NS_INTERFACE_MAP_ENTRY(nsIScrollable)
-   NS_INTERFACE_MAP_ENTRY(nsITextScroll)
-   NS_INTERFACE_MAP_ENTRY(nsIDocCharset)
-@@ -1372,16 +1373,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
-     return NS_OK; // JS may not handle returning of an error code
-   }
- 
-   if (DoAppRedirectIfNeeded(aURI, aLoadInfo, aFirstParty)) {
-     return NS_OK;
-   }
- 
-   nsCOMPtr<nsIURI> referrer;
-+  nsCOMPtr<nsIURI> originalURI;
-   nsCOMPtr<nsIInputStream> postStream;
-   nsCOMPtr<nsIInputStream> headersStream;
-   nsCOMPtr<nsISupports> owner;
-   bool inheritOwner = false;
-   bool ownerIsExplicit = false;
-   bool sendReferrer = true;
-   uint32_t referrerPolicy = mozilla::net::RP_Default;
-   bool isSrcdoc = false;
-@@ -1398,16 +1400,20 @@ nsDocShell::LoadURI(nsIURI* aURI,
-   if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
-       mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
-     StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
-   }
- 
-   // Extract the info from the DocShellLoadInfo struct...
-   if (aLoadInfo) {
-     aLoadInfo->GetReferrer(getter_AddRefs(referrer));
-+    nsCOMPtr<nsIDocShellLoadInfo_ESR38> liESR38 = do_QueryInterface(aLoadInfo);
-+    if (liESR38) {
-+      liESR38->GetOriginalURI(getter_AddRefs(originalURI));
-+    }
- 
-     nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
-     aLoadInfo->GetLoadType(&lt);
-     // Get the appropriate loadType from nsIDocShellLoadInfo type
-     loadType = ConvertDocShellLoadInfoToLoadType(lt);
- 
-     aLoadInfo->GetOwner(getter_AddRefs(owner));
-     aLoadInfo->GetInheritOwner(&inheritOwner);
-@@ -1652,34 +1658,35 @@ nsDocShell::LoadURI(nsIURI* aURI,
-   if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
-     flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
-   }
- 
-   if (isSrcdoc) {
-     flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
-   }
- 
--  return InternalLoad(aURI,
--                      referrer,
--                      referrerPolicy,
--                      owner,
--                      flags,
--                      target.get(),
--                      nullptr,      // No type hint
--                      NullString(), // No forced download
--                      postStream,
--                      headersStream,
--                      loadType,
--                      nullptr, // No SHEntry
--                      aFirstParty,
--                      srcdoc,
--                      sourceDocShell,
--                      baseURI,
--                      nullptr,  // No nsIDocShell
--                      nullptr); // No nsIRequest
-+  return InternalLoad2(aURI,
-+                       originalURI,
-+                       referrer,
-+                       referrerPolicy,
-+                       owner,
-+                       flags,
-+                       target.get(),
-+                       nullptr,      // No type hint
-+                       NullString(), // No forced download
-+                       postStream,
-+                       headersStream,
-+                       loadType,
-+                       nullptr, // No SHEntry
-+                       aFirstParty,
-+                       srcdoc,
-+                       sourceDocShell,
-+                       baseURI,
-+                       nullptr,  // No nsIDocShell
-+                       nullptr); // No nsIRequest
- }
- 
- NS_IMETHODIMP
- nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
-                        const nsACString& aContentType,
-                        const nsACString& aContentCharset,
-                        nsIDocShellLoadInfo* aLoadInfo)
- {
-@@ -5398,21 +5405,21 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
-   // end of the URL, so append it last.
-   errorPageUrl.AppendLiteral("&d=");
-   errorPageUrl.AppendASCII(escapedDescription.get());
- 
-   nsCOMPtr<nsIURI> errorPageURI;
-   rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
-   NS_ENSURE_SUCCESS(rv, rv);
- 
--  return InternalLoad(errorPageURI, nullptr, mozilla::net::RP_Default,
--                      nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr,
--                      nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
--                      nullptr, true, NullString(), this, nullptr, nullptr,
--                      nullptr);
-+  return InternalLoad2(errorPageURI, nullptr, nullptr, mozilla::net::RP_Default,
-+                       nullptr, INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr,
-+                       nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
-+                       nullptr, true, NullString(), this, nullptr, nullptr,
-+                       nullptr);
- }
- 
- NS_IMETHODIMP
- nsDocShell::Reload(uint32_t aReloadFlags)
- {
-   if (!IsNavigationAllowed()) {
-     return NS_OK; // JS may not handle returning of an error code
-   }
-@@ -5448,44 +5455,54 @@ nsDocShell::Reload(uint32_t aReloadFlags
-     nsCOMPtr<nsIDocument> doc(GetDocument());
- 
-     // Do not inherit owner from document
-     uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
-     nsAutoString srcdoc;
-     nsIPrincipal* principal = nullptr;
-     nsAutoString contentTypeHint;
-     nsCOMPtr<nsIURI> baseURI;
-+    nsCOMPtr<nsIURI> originalURI;
-     if (doc) {
-       principal = doc->NodePrincipal();
-       doc->GetContentType(contentTypeHint);
- 
-       if (doc->IsSrcdocDocument()) {
-         doc->GetSrcdocData(srcdoc);
-         flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
-         baseURI = doc->GetBaseURI();
-       }
--    }
--    rv = InternalLoad(mCurrentURI,
--                      mReferrerURI,
--                      mReferrerPolicy,
--                      principal,
--                      flags,
--                      nullptr,         // No window target
--                      NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
--                      NullString(),    // No forced download
--                      nullptr,         // No post data
--                      nullptr,         // No headers data
--                      loadType,        // Load type
--                      nullptr,         // No SHEntry
--                      true,
--                      srcdoc,          // srcdoc argument for iframe
--                      this,            // For reloads we are the source
--                      baseURI,
--                      nullptr,         // No nsIDocShell
--                      nullptr);        // No nsIRequest
-+      nsCOMPtr<nsIChannel> chan = doc->GetChannel();
-+      if (chan) {
-+        nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
-+        if (httpChan) {
-+          httpChan->GetOriginalURI(getter_AddRefs(originalURI));
-+        }
-+      } 
-+    }
-+
-+    rv = InternalLoad2(mCurrentURI,
-+                       originalURI,
-+                       mReferrerURI,
-+                       mReferrerPolicy,
-+                       principal,
-+                       flags,
-+                       nullptr,         // No window target
-+                       NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
-+                       NullString(),    // No forced download
-+                       nullptr,         // No post data
-+                       nullptr,         // No headers data
-+                       loadType,        // Load type
-+                       nullptr,         // No SHEntry
-+                       true,
-+                       srcdoc,          // srcdoc argument for iframe
-+                       this,            // For reloads we are the source
-+                       baseURI,
-+                       nullptr,         // No nsIDocShell
-+                       nullptr);        // No nsIRequest
-   }
- 
-   return rv;
- }
- 
- NS_IMETHODIMP
- nsDocShell::Stop(uint32_t aStopFlags)
- {
-@@ -9463,27 +9480,28 @@ CopyFavicon(nsIURI* aOldURI, nsIURI* aNe
- #endif
- }
- 
- } // anonymous namespace
- 
- class InternalLoadEvent : public nsRunnable
- {
- public:
--  InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI,
-+  InternalLoadEvent(nsDocShell* aDocShell, nsIURI* aURI, nsIURI* aOriginalURI,
-                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
-                     nsISupports* aOwner, uint32_t aFlags,
-                     const char* aTypeHint, nsIInputStream* aPostData,
-                     nsIInputStream* aHeadersData, uint32_t aLoadType,
-                     nsISHEntry* aSHEntry, bool aFirstParty,
-                     const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell,
-                     nsIURI* aBaseURI)
-     : mSrcdoc(aSrcdoc)
-     , mDocShell(aDocShell)
-     , mURI(aURI)
-+    , mOriginalURI(aOriginalURI)
-     , mReferrer(aReferrer)
-     , mReferrerPolicy(aReferrerPolicy)
-     , mOwner(aOwner)
-     , mPostData(aPostData)
-     , mHeadersData(aHeadersData)
-     , mSHEntry(aSHEntry)
-     , mFlags(aFlags)
-     , mLoadType(aLoadType)
-@@ -9494,34 +9512,36 @@ public:
-     // Make sure to keep null things null as needed
-     if (aTypeHint) {
-       mTypeHint = aTypeHint;
-     }
-   }
- 
-   NS_IMETHOD Run()
-   {
--    return mDocShell->InternalLoad(mURI, mReferrer,
--                                   mReferrerPolicy,
--                                   mOwner, mFlags,
--                                   nullptr, mTypeHint.get(),
--                                   NullString(), mPostData, mHeadersData,
--                                   mLoadType, mSHEntry, mFirstParty,
--                                   mSrcdoc, mSourceDocShell, mBaseURI,
--                                   nullptr, nullptr);
-+    return mDocShell->InternalLoad2(mURI, mOriginalURI,
-+                                    mReferrer,
-+                                    mReferrerPolicy,
-+                                    mOwner, mFlags,
-+                                    nullptr, mTypeHint.get(),
-+                                    NullString(), mPostData, mHeadersData,
-+                                    mLoadType, mSHEntry, mFirstParty,
-+                                    mSrcdoc, mSourceDocShell, mBaseURI,
-+                                    nullptr, nullptr);
-   }
- 
- private:
-   // Use IDL strings so .get() returns null by default
-   nsXPIDLString mWindowTarget;
-   nsXPIDLCString mTypeHint;
-   nsString mSrcdoc;
- 
-   nsRefPtr<nsDocShell> mDocShell;
-   nsCOMPtr<nsIURI> mURI;
-+  nsCOMPtr<nsIURI> mOriginalURI;
-   nsCOMPtr<nsIURI> mReferrer;
-   uint32_t mReferrerPolicy;
-   nsCOMPtr<nsISupports> mOwner;
-   nsCOMPtr<nsIInputStream> mPostData;
-   nsCOMPtr<nsIInputStream> mHeadersData;
-   nsCOMPtr<nsISHEntry> mSHEntry;
-   uint32_t mFlags;
-   uint32_t mLoadType;
-@@ -9584,16 +9604,43 @@ nsDocShell::InternalLoad(nsIURI* aURI,
-                          nsISHEntry* aSHEntry,
-                          bool aFirstParty,
-                          const nsAString& aSrcdoc,
-                          nsIDocShell* aSourceDocShell,
-                          nsIURI* aBaseURI,
-                          nsIDocShell** aDocShell,
-                          nsIRequest** aRequest)
- {
-+  return InternalLoad2(aURI, nullptr, aReferrer, aReferrerPolicy, aOwner,
-+                       aFlags, aWindowTarget, aTypeHint, aFileName, aPostData,
-+                       aHeadersData, aLoadType, aSHEntry, aFirstParty, aSrcdoc,
-+                       aSourceDocShell, aBaseURI, aDocShell, aRequest);
-+}
-+
-+NS_IMETHODIMP
-+nsDocShell::InternalLoad2(nsIURI* aURI,
-+                          nsIURI* aOriginalURI,
-+                          nsIURI* aReferrer,
-+                          uint32_t aReferrerPolicy,
-+                          nsISupports* aOwner,
-+                          uint32_t aFlags,
-+                          const char16_t* aWindowTarget,
-+                          const char* aTypeHint,
-+                          const nsAString& aFileName,
-+                          nsIInputStream* aPostData,
-+                          nsIInputStream* aHeadersData,
-+                          uint32_t aLoadType,
-+                          nsISHEntry* aSHEntry,
-+                          bool aFirstParty,
-+                          const nsAString& aSrcdoc,
-+                          nsIDocShell* aSourceDocShell,
-+                          nsIURI* aBaseURI,
-+                          nsIDocShell** aDocShell,
-+                          nsIRequest** aRequest)
-+{
-   nsresult rv = NS_OK;
-   mOriginalUriString.Truncate();
- 
- #ifdef PR_LOGGING
-   if (gDocShellLeakLog && PR_LOG_TEST(gDocShellLeakLog, PR_LOG_DEBUG)) {
-     nsAutoCString spec;
-     if (aURI) {
-       aURI->GetSpec(spec);
-@@ -9831,34 +9878,58 @@ nsDocShell::InternalLoad(nsIURI* aURI,
-       targetDocShell = do_QueryInterface(webNav);
-     }
- 
-     //
-     // Transfer the load to the target DocShell...  Pass nullptr as the
-     // window target name from to prevent recursive retargeting!
-     //
-     if (NS_SUCCEEDED(rv) && targetDocShell) {
--      rv = targetDocShell->InternalLoad(aURI,
--                                        aReferrer,
--                                        aReferrerPolicy,
--                                        owner,
--                                        aFlags,
--                                        nullptr,         // No window target
--                                        aTypeHint,
--                                        NullString(),    // No forced download
--                                        aPostData,
--                                        aHeadersData,
--                                        aLoadType,
--                                        aSHEntry,
--                                        aFirstParty,
--                                        aSrcdoc,
--                                        aSourceDocShell,
--                                        aBaseURI,
--                                        aDocShell,
--                                        aRequest);
-+      nsCOMPtr<nsIDocShell_ESR38_2> dsESR38 = do_QueryInterface(targetDocShell);
-+      if (dsESR38) {
-+        rv = dsESR38->InternalLoad2(aURI,
-+                                    aOriginalURI,
-+                                    aReferrer,
-+                                    aReferrerPolicy,
-+                                    owner,
-+                                    aFlags,
-+                                    nullptr,         // No window target
-+                                    aTypeHint,
-+                                    NullString(),    // No forced download
-+                                    aPostData,
-+                                    aHeadersData,
-+                                    aLoadType,
-+                                    aSHEntry,
-+                                    aFirstParty,
-+                                    aSrcdoc,
-+                                    aSourceDocShell,
-+                                    aBaseURI,
-+                                    aDocShell,
-+                                    aRequest);
-+      } else {
-+        rv = targetDocShell->InternalLoad(aURI,
-+                                          aReferrer,
-+                                          aReferrerPolicy,
-+                                          owner,
-+                                          aFlags,
-+                                          nullptr,         // No window target
-+                                          aTypeHint,
-+                                          NullString(),    // No forced download
-+                                          aPostData,
-+                                          aHeadersData,
-+                                          aLoadType,
-+                                          aSHEntry,
-+                                          aFirstParty,
-+                                          aSrcdoc,
-+                                          aSourceDocShell,
-+                                          aBaseURI,
-+                                          aDocShell,
-+                                          aRequest);
-+      }
-+
-       if (rv == NS_ERROR_NO_CONTENT) {
-         // XXXbz except we never reach this code!
-         if (isNewWindow) {
-           //
-           // At this point, a new window has been created, but the
-           // URI did not have any data associated with it...
-           //
-           // So, the best we can do, is to tear down the new window
-@@ -9913,17 +9984,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
-       // the unload event also a replace load, so we don't
-       // create extra history entries.
-       if (LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
-         mLoadType = LOAD_NORMAL_REPLACE;
-       }
- 
-       // Do this asynchronously
-       nsCOMPtr<nsIRunnable> ev =
--        new InternalLoadEvent(this, aURI, aReferrer,
-+        new InternalLoadEvent(this, aURI, aOriginalURI, aReferrer,
-                               aReferrerPolicy, aOwner, aFlags,
-                               aTypeHint, aPostData, aHeadersData,
-                               aLoadType, aSHEntry, aFirstParty, aSrcdoc,
-                               aSourceDocShell, aBaseURI);
-       return NS_DispatchToCurrentThread(ev);
-     }
- 
-     // Just ignore this load attempt
-@@ -10371,17 +10442,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
-   }
- 
-   net::PredictorLearn(aURI, nullptr,
-                       nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, this);
-   net::PredictorPredict(aURI, nullptr,
-                         nsINetworkPredictor::PREDICT_LOAD, this, nullptr);
- 
-   nsCOMPtr<nsIRequest> req;
--  rv = DoURILoad(aURI, aReferrer,
-+  rv = DoURILoad(aURI, aOriginalURI, aReferrer,
-                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
-                  aReferrerPolicy,
-                  owner, aTypeHint, aFileName, aPostData, aHeadersData,
-                  aFirstParty, aDocShell, getter_AddRefs(req),
-                  (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
-                  (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
-                  (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
-                  srcdoc, aBaseURI, contentType);
-@@ -10445,16 +10516,17 @@ nsDocShell::GetInheritedPrincipal(bool a
-     return docPrincipal;
-   }
- 
-   return nullptr;
- }
- 
- nsresult
- nsDocShell::DoURILoad(nsIURI* aURI,
-+                      nsIURI* aOriginalURI,
-                       nsIURI* aReferrerURI,
-                       bool aSendReferrer,
-                       uint32_t aReferrerPolicy,
-                       nsISupports* aOwner,
-                       const char* aTypeHint,
-                       const nsAString& aFileName,
-                       nsIInputStream* aPostData,
-                       nsIInputStream* aHeadersData,
-@@ -10652,17 +10724,22 @@ nsDocShell::DoURILoad(nsIURI* aURI,
-   }
- 
-   // Make sure to give the caller a channel if we managed to create one
-   // This is important for correct error page/session history interaction
-   if (aRequest) {
-     NS_ADDREF(*aRequest = channel);
-   }
- 
--  channel->SetOriginalURI(aURI);
-+  if (aOriginalURI) {
-+    channel->SetOriginalURI(aOriginalURI);
-+  } else {
-+    channel->SetOriginalURI(aURI);
-+  }
-+
-   if (aTypeHint && *aTypeHint) {
-     channel->SetContentType(nsDependentCString(aTypeHint));
-     mContentTypeHint = aTypeHint;
-   } else {
-     mContentTypeHint.Truncate();
-   }
- 
-   if (!aFileName.IsVoid()) {
-@@ -11624,16 +11701,20 @@ nsDocShell::AddState(JS::Handle<JS::Valu
- 
-     // AddToSessionHistory may not modify mOSHE.  In case it doesn't,
-     // we'll just set mOSHE here.
-     mOSHE = newSHEntry;
- 
-   } else {
-     newSHEntry = mOSHE;
-     newSHEntry->SetURI(newURI);
-+    nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(newSHEntry);
-+    if (entryESR38) {
-+      entryESR38->SetOriginalURI(newURI);
-+    }
-   }
- 
-   // Step 4: Modify new/original session history entry and clear its POST
-   // data, if there is any.
-   newSHEntry->SetStateData(scContainer);
-   newSHEntry->SetPostData(nullptr);
- 
-   // If this push/replaceState changed the document's current URI and the new
-@@ -11816,16 +11897,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
- 
-     if (!entry) {
-       return NS_ERROR_OUT_OF_MEMORY;
-     }
-   }
- 
-   // Get the post data & referrer
-   nsCOMPtr<nsIInputStream> inputStream;
-+  nsCOMPtr<nsIURI> originalURI;
-   nsCOMPtr<nsIURI> referrerURI;
-   uint32_t referrerPolicy = mozilla::net::RP_Default;
-   nsCOMPtr<nsISupports> cacheKey;
-   nsCOMPtr<nsISupports> owner = aOwner;
-   bool expired = false;
-   bool discardLayoutState = false;
-   nsCOMPtr<nsICachingChannel> cacheChannel;
-   if (aChannel) {
-@@ -11843,16 +11925,17 @@ nsDocShell::AddToSessionHistory(nsIURI* 
-     if (!httpChannel) {
-       GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
-     }
-     if (httpChannel) {
-       nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
-       if (uploadChannel) {
-         uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
-       }
-+      httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
-       httpChannel->GetReferrer(getter_AddRefs(referrerURI));
-       httpChannel->GetReferrerPolicy(&referrerPolicy);
- 
-       discardLayoutState = ShouldDiscardLayoutState(httpChannel);
-     }
-     aChannel->GetOwner(getter_AddRefs(owner));
-     if (!owner) {
-       nsCOMPtr<nsILoadInfo> loadInfo;
-@@ -11875,16 +11958,21 @@ nsDocShell::AddToSessionHistory(nsIURI* 
-                 EmptyString(),     // Title
-                 inputStream,       // Post data stream
-                 nullptr,           // LayoutHistory state
-                 cacheKey,          // CacheKey
-                 mContentTypeHint,  // Content-type
-                 owner,             // Channel or provided owner
-                 mHistoryID,
-                 mDynamicallyCreated);
-+
-+  nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(entry);
-+  if (entryESR38) {
-+    entryESR38->SetOriginalURI(originalURI);
-+  }
-   entry->SetReferrerURI(referrerURI);
-   entry->SetReferrerPolicy(referrerPolicy);
-   nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
-   if (inStrmChan) {
-     bool isSrcdocChannel;
-     inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
-     if (isSrcdocChannel) {
-       nsAutoString srcdoc;
-@@ -11976,25 +12064,32 @@ nsDocShell::AddToSessionHistory(nsIURI* 
- nsresult
- nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
- {
-   if (!IsNavigationAllowed()) {
-     return NS_OK;
-   }
- 
-   nsCOMPtr<nsIURI> uri;
-+  nsCOMPtr<nsIURI> originalURI;
-   nsCOMPtr<nsIInputStream> postData;
-   nsCOMPtr<nsIURI> referrerURI;
-   uint32_t referrerPolicy;
-   nsAutoCString contentType;
-   nsCOMPtr<nsISupports> owner;
- 
-   NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
- 
-   NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
-+
-+  nsCOMPtr<nsISHEntry_ESR38> entryESR38 = do_QueryInterface(aEntry);
-+  if (entryESR38) {
-+    NS_ENSURE_SUCCESS(entryESR38->GetOriginalURI(getter_AddRefs(originalURI)),
-+                      NS_ERROR_FAILURE);
-+  }
-   NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
-                     NS_ERROR_FAILURE);
-   NS_ENSURE_SUCCESS(aEntry->GetReferrerPolicy(&referrerPolicy),
-                     NS_ERROR_FAILURE);
-   NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)),
-                     NS_ERROR_FAILURE);
-   NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE);
-   NS_ENSURE_SUCCESS(aEntry->GetOwner(getter_AddRefs(owner)), NS_ERROR_FAILURE);
-@@ -12064,34 +12159,35 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
-   } else {
-     srcdoc = NullString();
-   }
- 
-   // Passing nullptr as aSourceDocShell gives the same behaviour as before
-   // aSourceDocShell was introduced. According to spec we should be passing
-   // the source browsing context that was used when the history entry was
-   // first created. bug 947716 has been created to address this issue.
--  rv = InternalLoad(uri,
--                    referrerURI,
--                    referrerPolicy,
--                    owner,
--                    flags,
--                    nullptr,            // No window target
--                    contentType.get(),  // Type hint
--                    NullString(),       // No forced file download
--                    postData,           // Post data stream
--                    nullptr,            // No headers stream
--                    aLoadType,          // Load type
--                    aEntry,             // SHEntry
--                    true,
--                    srcdoc,
--                    nullptr,            // Source docshell, see comment above
--                    baseURI,
--                    nullptr,            // No nsIDocShell
--                    nullptr);           // No nsIRequest
-+  rv = InternalLoad2(uri,
-+                     originalURI,
-+                     referrerURI,
-+                     referrerPolicy,
-+                     owner,
-+                     flags,
-+                     nullptr,            // No window target
-+                     contentType.get(),  // Type hint
-+                     NullString(),       // No forced file download
-+                     postData,           // Post data stream
-+                     nullptr,            // No headers stream
-+                     aLoadType,          // Load type
-+                     aEntry,             // SHEntry
-+                     true,
-+                     srcdoc,
-+                     nullptr,            // Source docshell, see comment above
-+                     baseURI,
-+                     nullptr,            // No nsIDocShell
-+                     nullptr);           // No nsIRequest
-   return rv;
- }
- 
- NS_IMETHODIMP
- nsDocShell::GetShouldSaveLayoutState(bool* aShould)
- {
-   *aShould = false;
-   if (mOSHE) {
-@@ -13527,35 +13623,36 @@ nsDocShell::OnLinkClickSync(nsIContent* 
-   // with it under InternalLoad; we do _not_ want to change the URI
-   // our caller passed in.
-   nsCOMPtr<nsIURI> clonedURI;
-   aURI->Clone(getter_AddRefs(clonedURI));
-   if (!clonedURI) {
-     return NS_ERROR_OUT_OF_MEMORY;
-   }
- 
--  nsresult rv = InternalLoad(clonedURI,                 // New URI
--                             referer,                   // Referer URI
--                             refererPolicy,             // Referer policy
--                             aContent->NodePrincipal(), // Owner is our node's
--                                                        // principal
--                             flags,
--                             target.get(),              // Window target
--                             NS_LossyConvertUTF16toASCII(typeHint).get(),
--                             aFileName,                 // Download as file
--                             aPostDataStream,           // Post data stream
--                             aHeadersDataStream,        // Headers stream
--                             LOAD_LINK,                 // Load type
--                             nullptr,                   // No SHEntry
--                             true,                      // first party site
--                             NullString(),              // No srcdoc
--                             this,                      // We are the source
--                             nullptr,                   // baseURI not needed
--                             aDocShell,                 // DocShell out-param
--                             aRequest);                 // Request out-param
-+  nsresult rv = InternalLoad2(clonedURI,                 // New URI
-+                              nullptr,                   // Original URI
-+                              referer,                   // Referer URI
-+                              refererPolicy,             // Referer policy
-+                              aContent->NodePrincipal(), // Owner is our node's
-+                                                         // principal
-+                              flags,
-+                              target.get(),              // Window target
-+                              NS_LossyConvertUTF16toASCII(typeHint).get(),
-+                              aFileName,                 // Download as file
-+                              aPostDataStream,           // Post data stream
-+                              aHeadersDataStream,        // Headers stream
-+                              LOAD_LINK,                 // Load type
-+                              nullptr,                   // No SHEntry
-+                              true,                      // first party site
-+                              NullString(),              // No srcdoc
-+                              this,                      // We are the source
-+                              nullptr,                   // baseURI not needed
-+                              aDocShell,                 // DocShell out-param
-+                              aRequest);                 // Request out-param
-   if (NS_SUCCEEDED(rv)) {
-     DispatchPings(aContent, aURI, referer, refererPolicy);
-   }
-   return rv;
- }
- 
- NS_IMETHODIMP
- nsDocShell::OnOverLink(nsIContent* aContent,
-diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
---- a/docshell/base/nsDocShell.h
-+++ b/docshell/base/nsDocShell.h
-@@ -132,17 +132,17 @@ enum eCharsetReloadState
- };
- 
- //*****************************************************************************
- //***    nsDocShell
- //*****************************************************************************
- 
- class nsDocShell final
-   : public nsDocLoader
--  , public nsIDocShell_ESR38
-+  , public nsIDocShell_ESR38_2
-   , public nsIWebNavigation
-   , public nsIBaseWindow
-   , public nsIScrollable
-   , public nsITextScroll
-   , public nsIDocCharset
-   , public nsIContentViewerContainer
-   , public nsIRefreshURI
-   , public nsIWebProgressListener
-@@ -164,16 +164,17 @@ public:
-   nsDocShell();
- 
-   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
- 
-   virtual nsresult Init() override;
- 
-   NS_DECL_ISUPPORTS_INHERITED
- 
-+  NS_DECL_NSIDOCSHELL_ESR38_2
-   NS_DECL_NSIDOCSHELL_ESR38
-   NS_DECL_NSIDOCSHELL
-   NS_DECL_NSIDOCSHELLTREEITEM
-   NS_DECL_NSIWEBNAVIGATION
-   NS_DECL_NSIBASEWINDOW
-   NS_DECL_NSISCROLLABLE
-   NS_DECL_NSITEXTSCROLL
-   NS_DECL_NSIDOCCHARSET
-@@ -312,17 +313,20 @@ protected:
-   // at the parent.
-   nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument);
- 
-   // Actually open a channel and perform a URI load.  Note: whatever owner is
-   // passed to this function will be set on the channel.  Callers who wish to
-   // not have an owner on the channel should just pass null.
-   // If aSrcdoc is not void, the load will be considered as a srcdoc load,
-   // and the contents of aSrcdoc will be loaded instead of aURI.
-+  // aOriginalURI will be set as the originalURI on the channel that does the
-+  // load. If aOriginalURI is null, aURI will be set as the originalURI.
-   nsresult DoURILoad(nsIURI* aURI,
-+                     nsIURI* aOriginalURI,
-                      nsIURI* aReferrer,
-                      bool aSendReferrer,
-                      uint32_t aReferrerPolicy,
-                      nsISupports* aOwner,
-                      const char* aTypeHint,
-                      const nsAString& aFileName,
-                      nsIInputStream* aPostData,
-                      nsIInputStream* aHeadersData,
-diff --git a/docshell/base/nsDocShellLoadInfo.cpp b/docshell/base/nsDocShellLoadInfo.cpp
---- a/docshell/base/nsDocShellLoadInfo.cpp
-+++ b/docshell/base/nsDocShellLoadInfo.cpp
-@@ -34,16 +34,17 @@ nsDocShellLoadInfo::~nsDocShellLoadInfo(
- // nsDocShellLoadInfo::nsISupports
- //*****************************************************************************
- 
- NS_IMPL_ADDREF(nsDocShellLoadInfo)
- NS_IMPL_RELEASE(nsDocShellLoadInfo)
- 
- NS_INTERFACE_MAP_BEGIN(nsDocShellLoadInfo)
-   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDocShellLoadInfo)
-+  NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo_ESR38)
-   NS_INTERFACE_MAP_ENTRY(nsIDocShellLoadInfo)
- NS_INTERFACE_MAP_END
- 
- //*****************************************************************************
- // nsDocShellLoadInfo::nsIDocShellLoadInfo
- //*****************************************************************************
- 
- NS_IMETHODIMP
-@@ -59,16 +60,33 @@ nsDocShellLoadInfo::GetReferrer(nsIURI**
- NS_IMETHODIMP
- nsDocShellLoadInfo::SetReferrer(nsIURI* aReferrer)
- {
-   mReferrer = aReferrer;
-   return NS_OK;
- }
- 
- NS_IMETHODIMP
-+nsDocShellLoadInfo::GetOriginalURI(nsIURI** aOriginalURI)
-+{
-+  NS_ENSURE_ARG_POINTER(aOriginalURI);
-+
-+  *aOriginalURI = mOriginalURI;
-+  NS_IF_ADDREF(*aOriginalURI);
-+  return NS_OK;
-+}
-+
-+NS_IMETHODIMP
-+nsDocShellLoadInfo::SetOriginalURI(nsIURI* aOriginalURI)
-+{
-+  mOriginalURI = aOriginalURI;
-+  return NS_OK;
-+}
-+
-+NS_IMETHODIMP
- nsDocShellLoadInfo::GetOwner(nsISupports** aOwner)
- {
-   NS_ENSURE_ARG_POINTER(aOwner);
- 
-   *aOwner = mOwner;
-   NS_IF_ADDREF(*aOwner);
-   return NS_OK;
- }
-diff --git a/docshell/base/nsDocShellLoadInfo.h b/docshell/base/nsDocShellLoadInfo.h
---- a/docshell/base/nsDocShellLoadInfo.h
-+++ b/docshell/base/nsDocShellLoadInfo.h
-@@ -14,29 +14,31 @@
- // Interfaces Needed
- #include "nsIDocShellLoadInfo.h"
- 
- class nsIInputStream;
- class nsISHEntry;
- class nsIURI;
- class nsIDocShell;
- 
--class nsDocShellLoadInfo : public nsIDocShellLoadInfo
-+class nsDocShellLoadInfo : public nsIDocShellLoadInfo_ESR38
- {
- public:
-   nsDocShellLoadInfo();
- 
-   NS_DECL_ISUPPORTS
-+  NS_DECL_NSIDOCSHELLLOADINFO_ESR38
-   NS_DECL_NSIDOCSHELLLOADINFO
- 
- protected:
-   virtual ~nsDocShellLoadInfo();
- 
- protected:
-   nsCOMPtr<nsIURI> mReferrer;
-+  nsCOMPtr<nsIURI> mOriginalURI;
-   nsCOMPtr<nsISupports> mOwner;
-   bool mInheritOwner;
-   bool mOwnerIsExplicit;
-   bool mSendReferrer;
-   nsDocShellInfoReferrerPolicy mReferrerPolicy;
-   nsDocShellInfoLoadType mLoadType;
-   nsCOMPtr<nsISHEntry> mSHEntry;
-   nsString mTarget;
-diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
---- a/docshell/base/nsIDocShell.idl
-+++ b/docshell/base/nsIDocShell.idl
-@@ -1059,8 +1059,66 @@ interface nsIDocShell : nsIDocShellTreeI
- interface nsIDocShell_ESR38 : nsIDocShell
- {
-   /**
-    * True if new child docshells should allow content retargeting.
-    * Setting allowContentRetargeting also overwrites this value.
-    */
-   [infallible] attribute boolean allowContentRetargetingOnChildren;
- };
-+
-+[scriptable, builtinclass, uuid(607604b6-8fe0-4d2c-8a6c-44f5f31a6e02)]
-+interface nsIDocShell_ESR38_2 : nsIDocShell_ESR38
-+{
-+  /**
-+   * Loads the given URI.  This method is identical to loadURI(...) except
-+   * that its parameter list is broken out instead of being packaged inside
-+   * of an nsIDocShellLoadInfo object...
-+   *
-+   * @param aURI            - The URI to load.
-+   * @param aOriginalURI    - The URI to set as the originalURI on the channel
-+   *                          that does the load. If null, aURI will be set as
-+   *                          the originalURI.
-+   * @param aReferrer       - Referring URI
-+   * @param aReferrerPolicy - Referrer policy
-+   * @param aOwner          - Owner (security principal) 
-+   * @param aInheritOwner   - Flag indicating whether the owner of the current
-+   *                          document should be inherited if aOwner is null.
-+   * @param aStopActiveDoc  - Flag indicating whether loading the current
-+   *                          document should be stopped.
-+   * @param aWindowTarget   - Window target for the load.
-+   * @param aTypeHint       - A hint as to the content-type of the resulting
-+   *                          data.  May be null or empty if no hint.
-+   * @param aFileName       - Non-null when the link should be downloaded as
-+                              the given filename.
-+   * @param aPostDataStream - Post data stream (if POSTing)
-+   * @param aHeadersStream  - Stream containing "extra" request headers...
-+   * @param aLoadFlags      - Flags to modify load behaviour. Flags are defined
-+   *                          in nsIWebNavigation.
-+   * @param aSHEntry        - Active Session History entry (if loading from SH)
-+   * @param aSrcdoc           When INTERNAL_LOAD_FLAGS_IS_SRCDOC is set, the
-+   *                          contents of this parameter will be loaded instead
-+   *                          of aURI.
-+   * @param aSourceDocShell - The source browsing context for the navigation.
-+   * @param aBaseURI        - The base URI to be used for the load.  Set in
-+   *                          srcdoc loads as it cannot otherwise be inferred
-+   *                          in certain situations such as view-source.
-+   */
-+  [noscript]void internalLoad2(in nsIURI aURI,
-+                               in nsIURI aOriginalURI,
-+                               in nsIURI aReferrer,
-+                               in unsigned long aReferrerPolicy,
-+                               in nsISupports aOwner,
-+                               in uint32_t aFlags,
-+                               in wstring aWindowTarget,
-+                               in string aTypeHint,
-+                               in AString aFileName,
-+                               in nsIInputStream aPostDataStream,
-+                               in nsIInputStream aHeadersStream,
-+                               in unsigned long aLoadFlags,
-+                               in nsISHEntry aSHEntry,
-+                               in boolean firstParty,
-+                               in AString aSrcdoc,
-+                               in nsIDocShell aSourceDocShell,
-+                               in nsIURI aBaseURI,
-+                               out nsIDocShell aDocShell,
-+                               out nsIRequest aRequest);
-+};
-diff --git a/docshell/base/nsIDocShellLoadInfo.idl b/docshell/base/nsIDocShellLoadInfo.idl
---- a/docshell/base/nsIDocShellLoadInfo.idl
-+++ b/docshell/base/nsIDocShellLoadInfo.idl
-@@ -106,8 +106,17 @@ interface nsIDocShellLoadInfo : nsISuppo
-     attribute nsIDocShell sourceDocShell;
- 
-     /**
-      * Used for srcdoc loads to give view-source knowledge of the load's base
-      * URI as this information isn't embedded in the load's URI.
-      */
-     attribute nsIURI baseURI;
- };
-+
-+[scriptable, uuid(9d3bc466-5efe-414d-ae8b-3830b45877bb)]
-+interface nsIDocShellLoadInfo_ESR38 : nsIDocShellLoadInfo
-+{
-+    /**
-+     * The originalURI to be passed to nsIDocShell.internalLoad. May be null.
-+     */
-+    attribute nsIURI originalURI;
-+};
-diff --git a/docshell/shistory/public/nsISHEntry.idl b/docshell/shistory/public/nsISHEntry.idl
---- a/docshell/shistory/public/nsISHEntry.idl
-+++ b/docshell/shistory/public/nsISHEntry.idl
-@@ -319,8 +319,18 @@ interface nsISHEntryInternal : nsISuppor
- #define NS_SHENTRY_CID \
- {0xbfd1a791, 0xad9f, 0x11d3, {0xbd, 0xc7, 0x0, 0x50, 0x4, 0xa, 0x9b, 0x44}}
- 
- #define NS_SHENTRY_CONTRACTID \
-     "@mozilla.org/browser/session-history-entry;1"
- 
- %}
- 
-+[scriptable, uuid(e45ab6ef-3485-449c-b91c-0846b2bf6faf)]
-+interface nsISHEntry_ESR38 : nsISHEntry
-+{
-+    /**
-+     * A readonly property that returns the original URI of the current entry.
-+     * If an entry is the result of a redirect this attribute holds original
-+     * URI. The object returned is of type nsIURI
-+     */
-+    attribute nsIURI originalURI;
-+};
-diff --git a/docshell/shistory/src/nsSHEntry.cpp b/docshell/shistory/src/nsSHEntry.cpp
---- a/docshell/shistory/src/nsSHEntry.cpp
-+++ b/docshell/shistory/src/nsSHEntry.cpp
-@@ -38,16 +38,17 @@ nsSHEntry::nsSHEntry()
-   , mIsSrcdocEntry(false)
- {
-   mShared = new nsSHEntryShared();
- }
- 
- nsSHEntry::nsSHEntry(const nsSHEntry &other)
-   : mShared(other.mShared)
-   , mURI(other.mURI)
-+  , mOriginalURI(other.mOriginalURI)
-   , mReferrerURI(other.mReferrerURI)
-   , mReferrerPolicy(other.mReferrerPolicy)
-   , mTitle(other.mTitle)
-   , mPostData(other.mPostData)
-   , mLoadType(0)         // XXX why not copy?
-   , mID(other.mID)
-   , mScrollPositionX(0)  // XXX why not copy?
-   , mScrollPositionY(0)  // XXX why not copy?
-@@ -74,17 +75,17 @@ nsSHEntry::~nsSHEntry()
-   // Null out the mParent pointers on all our kids.
-   mChildren.EnumerateForwards(ClearParentPtr, nullptr);
- }
- 
- //*****************************************************************************
- //    nsSHEntry: nsISupports
- //*****************************************************************************
- 
--NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry, nsISHEntryInternal)
-+NS_IMPL_ISUPPORTS(nsSHEntry, nsISHContainer, nsISHEntry_ESR38, nsISHEntry, nsISHEntryInternal)
- 
- //*****************************************************************************
- //    nsSHEntry: nsISHEntry
- //*****************************************************************************
- 
- NS_IMETHODIMP nsSHEntry::SetScrollPosition(int32_t x, int32_t y)
- {
-   mScrollPositionX = x;
-@@ -119,16 +120,29 @@ NS_IMETHODIMP nsSHEntry::GetURI(nsIURI**
- }
- 
- NS_IMETHODIMP nsSHEntry::SetURI(nsIURI* aURI)
- {
-   mURI = aURI;
-   return NS_OK;
- }
- 
-+NS_IMETHODIMP nsSHEntry::GetOriginalURI(nsIURI** aOriginalURI)
-+{
-+  *aOriginalURI = mOriginalURI;
-+  NS_IF_ADDREF(*aOriginalURI);
-+  return NS_OK;
-+}
-+
-+NS_IMETHODIMP nsSHEntry::SetOriginalURI(nsIURI* aOriginalURI)
-+{
-+  mOriginalURI = aOriginalURI;
-+  return NS_OK;
-+}
-+
- NS_IMETHODIMP nsSHEntry::GetReferrerURI(nsIURI **aReferrerURI)
- {
-   *aReferrerURI = mReferrerURI;
-   NS_IF_ADDREF(*aReferrerURI);
-   return NS_OK;
- }
- 
- NS_IMETHODIMP nsSHEntry::SetReferrerURI(nsIURI *aReferrerURI)
-diff --git a/docshell/shistory/src/nsSHEntry.h b/docshell/shistory/src/nsSHEntry.h
---- a/docshell/shistory/src/nsSHEntry.h
-+++ b/docshell/shistory/src/nsSHEntry.h
-@@ -17,25 +17,26 @@
- // Interfaces needed
- #include "nsISHEntry.h"
- #include "nsISHContainer.h"
- 
- class nsSHEntryShared;
- class nsIInputStream;
- class nsIURI;
- 
--class nsSHEntry final : public nsISHEntry,
-+class nsSHEntry final : public nsISHEntry_ESR38,
-                             public nsISHContainer,
-                             public nsISHEntryInternal
- {
- public: 
-   nsSHEntry();
-   nsSHEntry(const nsSHEntry &other);
- 
-   NS_DECL_ISUPPORTS
-+  NS_DECL_NSISHENTRY_ESR38
-   NS_DECL_NSISHENTRY
-   NS_DECL_NSISHENTRYINTERNAL
-   NS_DECL_NSISHCONTAINER
- 
-   void DropPresentationState();
- 
-   static nsresult Startup();
-   static void Shutdown();
-@@ -44,16 +45,17 @@ private:
-   ~nsSHEntry();
- 
-   // We share the state in here with other SHEntries which correspond to the
-   // same document.
-   nsRefPtr<nsSHEntryShared> mShared;
- 
-   // See nsSHEntry.idl for comments on these members.
-   nsCOMPtr<nsIURI>         mURI;
-+  nsCOMPtr<nsIURI>         mOriginalURI;
-   nsCOMPtr<nsIURI>         mReferrerURI;
-   uint32_t                 mReferrerPolicy;
-   nsString                 mTitle;
-   nsCOMPtr<nsIInputStream> mPostData;
-   uint32_t                 mLoadType;
-   uint32_t                 mID;
-   int32_t                  mScrollPositionX;
-   int32_t                  mScrollPositionY;
-diff --git a/docshell/shistory/src/nsSHistory.cpp b/docshell/shistory/src/nsSHistory.cpp
---- a/docshell/shistory/src/nsSHistory.cpp
-+++ b/docshell/shistory/src/nsSHistory.cpp
-@@ -1779,16 +1779,26 @@ nsSHistory::InitiateLoad(nsISHEntry * aF
-    * so that proper loadType is maintained through out a frameset
-    */
-   aFrameEntry->SetLoadType(aLoadType);    
-   aFrameDS->CreateLoadInfo (getter_AddRefs(loadInfo));
- 
-   loadInfo->SetLoadType(aLoadType);
-   loadInfo->SetSHEntry(aFrameEntry);
- 
-+  nsCOMPtr<nsIURI> originalURI;
-+  nsCOMPtr<nsISHEntry_ESR38> feESR38 = do_QueryInterface(aFrameEntry);
-+  if (feESR38) {
-+    feESR38->GetOriginalURI(getter_AddRefs(originalURI));
-+  }
-+  nsCOMPtr<nsIDocShellLoadInfo_ESR38> liESR38 = do_QueryInterface(loadInfo);
-+  if (liESR38) {
-+    liESR38->SetOriginalURI(originalURI);
-+  }
-+
-   nsCOMPtr<nsIURI> nextURI;
-   aFrameEntry->GetURI(getter_AddRefs(nextURI));
-   // Time   to initiate a document load
-   return aFrameDS->LoadURI(nextURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, false);
- 
- }
- 
- 
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch
deleted file mode 100644
index 2b711b1761..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1952-pt01.patch
+++ /dev/null
@@ -1,356 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/c1d67bd4c993
-
-# HG changeset patch
-# User Timothy Nikkel <tnikkel@gmail.com>
-# Date 1454023801 21600
-# Node ID c1d67bd4c993b9e344c68954e6f0392c82b81e38
-# Parent  530559abe159d3c23f078d673d30ff03d9c244e2
-Bug 1224979 - Check if we compute usable filters for the downscaler, and if not put the downscaler in error state so it's not used. r=edwin, a=al
-
-diff --git a/image/Downscaler.cpp b/image/Downscaler.cpp
-new file mode 100644
---- /dev/null
-+++ b/image/Downscaler.cpp
-@@ -0,0 +1,340 @@
-+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ *
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#include "Downscaler.h"
-+
-+#include <algorithm>
-+#include <ctime>
-+#include "gfxPrefs.h"
-+#include "image_operations.h"
-+#include "mozilla/SSE.h"
-+#include "convolver.h"
-+#include "skia/include/core/SkTypes.h"
-+
-+using std::max;
-+using std::swap;
-+
-+namespace mozilla {
-+namespace image {
-+
-+Downscaler::Downscaler(const nsIntSize& aTargetSize)
-+  : mTargetSize(aTargetSize)
-+  , mOutputBuffer(nullptr)
-+  , mXFilter(MakeUnique<skia::ConvolutionFilter1D>())
-+  , mYFilter(MakeUnique<skia::ConvolutionFilter1D>())
-+  , mWindowCapacity(0)
-+  , mHasAlpha(true)
-+  , mFlipVertically(false)
-+{
-+  MOZ_ASSERT(gfxPrefs::ImageDownscaleDuringDecodeEnabled(),
-+             "Downscaling even though downscale-during-decode is disabled?");
-+  MOZ_ASSERT(mTargetSize.width > 0 && mTargetSize.height > 0,
-+             "Invalid target size");
-+}
-+
-+Downscaler::~Downscaler()
-+{
-+  ReleaseWindow();
-+}
-+
-+void
-+Downscaler::ReleaseWindow()
-+{
-+  if (!mWindow) {
-+    return;
-+  }
-+
-+  for (int32_t i = 0; i < mWindowCapacity; ++i) {
-+    delete[] mWindow[i];
-+  }
-+
-+  mWindow = nullptr;
-+  mWindowCapacity = 0;
-+}
-+
-+nsresult
-+Downscaler::BeginFrame(const nsIntSize& aOriginalSize,
-+                       const Maybe<nsIntRect>& aFrameRect,
-+                       uint8_t* aOutputBuffer,
-+                       bool aHasAlpha,
-+                       bool aFlipVertically /* = false */)
-+{
-+  MOZ_ASSERT(aOutputBuffer);
-+  MOZ_ASSERT(mTargetSize != aOriginalSize,
-+             "Created a downscaler, but not downscaling?");
-+  MOZ_ASSERT(mTargetSize.width <= aOriginalSize.width,
-+             "Created a downscaler, but width is larger");
-+  MOZ_ASSERT(mTargetSize.height <= aOriginalSize.height,
-+             "Created a downscaler, but height is larger");
-+  MOZ_ASSERT(aOriginalSize.width > 0 && aOriginalSize.height > 0,
-+             "Invalid original size");
-+
-+  mFrameRect = aFrameRect.valueOr(nsIntRect(nsIntPoint(), aOriginalSize));
-+  MOZ_ASSERT(mFrameRect.x >= 0 && mFrameRect.y >= 0 &&
-+             mFrameRect.width >= 0 && mFrameRect.height >= 0,
-+             "Frame rect must have non-negative components");
-+  MOZ_ASSERT(nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
-+               .Contains(mFrameRect),
-+             "Frame rect must fit inside image");
-+  MOZ_ASSERT_IF(!nsIntRect(0, 0, aOriginalSize.width, aOriginalSize.height)
-+                  .IsEqualEdges(mFrameRect),
-+                aHasAlpha);
-+
-+  mOriginalSize = aOriginalSize;
-+  mScale = gfxSize(double(mOriginalSize.width) / mTargetSize.width,
-+                   double(mOriginalSize.height) / mTargetSize.height);
-+  mOutputBuffer = aOutputBuffer;
-+  mHasAlpha = aHasAlpha;
-+  mFlipVertically = aFlipVertically;
-+
-+  ReleaseWindow();
-+
-+  auto resizeMethod = skia::ImageOperations::RESIZE_LANCZOS3;
-+
-+  skia::resize::ComputeFilters(resizeMethod,
-+                               mOriginalSize.width, mTargetSize.width,
-+                               0, mTargetSize.width,
-+                               mXFilter.get());
-+
-+  if (mXFilter->max_filter() <= 0 || mXFilter->num_values() != mTargetSize.width) {
-+    NS_WARNING("Failed to compute filters for image downscaling");
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-+
-+  skia::resize::ComputeFilters(resizeMethod,
-+                               mOriginalSize.height, mTargetSize.height,
-+                               0, mTargetSize.height,
-+                               mYFilter.get());
-+
-+  if (mYFilter->max_filter() <= 0 || mYFilter->num_values() != mTargetSize.height) {
-+    NS_WARNING("Failed to compute filters for image downscaling");
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-+
-+  // Allocate the buffer, which contains scanlines of the original image.
-+  // pad by 15 to handle overreads by the simd code
-+  size_t bufferLen = mOriginalSize.width * sizeof(uint32_t) + 15;
-+  mRowBuffer.reset(new (fallible) uint8_t[bufferLen]);
-+  if (MOZ_UNLIKELY(!mRowBuffer)) {
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-+
-+  // Zero buffer to keep valgrind happy.
-+  memset(mRowBuffer.get(), 0, bufferLen);
-+
-+  // Allocate the window, which contains horizontally downscaled scanlines. (We
-+  // can store scanlines which are already downscale because our downscaling
-+  // filter is separable.)
-+  mWindowCapacity = mYFilter->max_filter();
-+  mWindow.reset(new (fallible) uint8_t*[mWindowCapacity]);
-+  if (MOZ_UNLIKELY(!mWindow)) {
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-+
-+  bool anyAllocationFailed = false;
-+  // pad by 15 to handle overreads by the simd code
-+  const int rowSize = mTargetSize.width * sizeof(uint32_t) + 15;
-+  for (int32_t i = 0; i < mWindowCapacity; ++i) {
-+    mWindow[i] = new (fallible) uint8_t[rowSize];
-+    anyAllocationFailed = anyAllocationFailed || mWindow[i] == nullptr;
-+  }
-+
-+  if (MOZ_UNLIKELY(anyAllocationFailed)) {
-+    // We intentionally iterate through the entire array even if an allocation
-+    // fails, to ensure that all the pointers in it are either valid or nullptr.
-+    // That in turn ensures that ReleaseWindow() can clean up correctly.
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-+
-+  ResetForNextProgressivePass();
-+
-+  return NS_OK;
-+}
-+
-+void
-+Downscaler::SkipToRow(int32_t aRow)
-+{
-+  if (mCurrentInLine < aRow) {
-+    ClearRow();
-+    do {
-+      CommitRow();
-+    } while (mCurrentInLine < aRow);
-+  }
-+}
-+
-+void
-+Downscaler::ResetForNextProgressivePass()
-+{
-+  mPrevInvalidatedLine = 0;
-+  mCurrentOutLine = 0;
-+  mCurrentInLine = 0;
-+  mLinesInBuffer = 0;
-+
-+  if (mFrameRect.IsEmpty()) {
-+    // Our frame rect is zero size; commit rows until the end of the image.
-+    SkipToRow(mOriginalSize.height - 1);
-+  } else {
-+    // If we have a vertical offset, commit rows to shift us past it.
-+    SkipToRow(mFrameRect.y);
-+  }
-+}
-+
-+static void
-+GetFilterOffsetAndLength(UniquePtr<skia::ConvolutionFilter1D>& aFilter,
-+                         int32_t aOutputImagePosition,
-+                         int32_t* aFilterOffsetOut,
-+                         int32_t* aFilterLengthOut)
-+{
-+  MOZ_ASSERT(aOutputImagePosition < aFilter->num_values());
-+  aFilter->FilterForValue(aOutputImagePosition,
-+                          aFilterOffsetOut,
-+                          aFilterLengthOut);
-+}
-+
-+void
-+Downscaler::ClearRow(uint32_t aStartingAtCol)
-+{
-+  MOZ_ASSERT(int64_t(mOriginalSize.width) > int64_t(aStartingAtCol));
-+  uint32_t bytesToClear = (mOriginalSize.width - aStartingAtCol)
-+                        * sizeof(uint32_t);
-+  memset(mRowBuffer.get() + (aStartingAtCol * sizeof(uint32_t)),
-+         0, bytesToClear);
-+}
-+
-+void
-+Downscaler::CommitRow()
-+{
-+  MOZ_ASSERT(mOutputBuffer, "Should have a current frame");
-+  MOZ_ASSERT(mCurrentInLine < mOriginalSize.height, "Past end of input");
-+
-+  if (mCurrentOutLine < mTargetSize.height) {
-+    int32_t filterOffset = 0;
-+    int32_t filterLength = 0;
-+    GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
-+                             &filterOffset, &filterLength);
-+
-+    int32_t inLineToRead = filterOffset + mLinesInBuffer;
-+    MOZ_ASSERT(mCurrentInLine <= inLineToRead, "Reading past end of input");
-+    if (mCurrentInLine == inLineToRead) {
-+      skia::ConvolveHorizontally(mRowBuffer.get(), *mXFilter,
-+                                 mWindow[mLinesInBuffer++], mHasAlpha,
-+                                 supports_sse2());
-+    }
-+
-+    MOZ_ASSERT(mCurrentOutLine < mTargetSize.height,
-+               "Writing past end of output");
-+
-+    while (mLinesInBuffer == filterLength) {
-+      DownscaleInputLine();
-+
-+      if (mCurrentOutLine == mTargetSize.height) {
-+        break;  // We're done.
-+      }
-+
-+      GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
-+                               &filterOffset, &filterLength);
-+    }
-+  }
-+
-+  mCurrentInLine += 1;
-+
-+  // If we're at the end of the part of the original image that has data, commit
-+  // rows to shift us to the end.
-+  if (mCurrentInLine == (mFrameRect.y + mFrameRect.height)) {
-+    SkipToRow(mOriginalSize.height - 1);
-+  }
-+}
-+
-+bool
-+Downscaler::HasInvalidation() const
-+{
-+  return mCurrentOutLine > mPrevInvalidatedLine;
-+}
-+
-+DownscalerInvalidRect
-+Downscaler::TakeInvalidRect()
-+{
-+  if (MOZ_UNLIKELY(!HasInvalidation())) {
-+    return DownscalerInvalidRect();
-+  }
-+
-+  DownscalerInvalidRect invalidRect;
-+
-+  // Compute the target size invalid rect.
-+  if (mFlipVertically) {
-+    // We need to flip it. This will implicitly flip the original size invalid
-+    // rect, since we compute it by scaling this rect.
-+    invalidRect.mTargetSizeRect =
-+      IntRect(0, mTargetSize.height - mCurrentOutLine,
-+              mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
-+  } else {
-+    invalidRect.mTargetSizeRect =
-+      IntRect(0, mPrevInvalidatedLine,
-+              mTargetSize.width, mCurrentOutLine - mPrevInvalidatedLine);
-+  }
-+
-+  mPrevInvalidatedLine = mCurrentOutLine;
-+
-+  // Compute the original size invalid rect.
-+  invalidRect.mOriginalSizeRect = invalidRect.mTargetSizeRect;
-+  invalidRect.mOriginalSizeRect.ScaleRoundOut(mScale.width, mScale.height);
-+
-+  return invalidRect;
-+}
-+
-+void
-+Downscaler::DownscaleInputLine()
-+{
-+  typedef skia::ConvolutionFilter1D::Fixed FilterValue;
-+
-+  MOZ_ASSERT(mOutputBuffer);
-+  MOZ_ASSERT(mCurrentOutLine < mTargetSize.height,
-+             "Writing past end of output");
-+
-+  int32_t filterOffset = 0;
-+  int32_t filterLength = 0;
-+  MOZ_ASSERT(mCurrentOutLine < mYFilter->num_values());
-+  auto filterValues =
-+    mYFilter->FilterForValue(mCurrentOutLine, &filterOffset, &filterLength);
-+
-+  int32_t currentOutLine = mFlipVertically
-+                         ? mTargetSize.height - (mCurrentOutLine + 1)
-+                         : mCurrentOutLine;
-+  MOZ_ASSERT(currentOutLine >= 0);
-+
-+  uint8_t* outputLine =
-+    &mOutputBuffer[currentOutLine * mTargetSize.width * sizeof(uint32_t)];
-+  skia::ConvolveVertically(static_cast<const FilterValue*>(filterValues),
-+                           filterLength, mWindow.get(), mXFilter->num_values(),
-+                           outputLine, mHasAlpha, supports_sse2());
-+
-+  mCurrentOutLine += 1;
-+
-+  if (mCurrentOutLine == mTargetSize.height) {
-+    // We're done.
-+    return;
-+  }
-+
-+  int32_t newFilterOffset = 0;
-+  int32_t newFilterLength = 0;
-+  GetFilterOffsetAndLength(mYFilter, mCurrentOutLine,
-+                           &newFilterOffset, &newFilterLength);
-+
-+  int diff = newFilterOffset - filterOffset;
-+  MOZ_ASSERT(diff >= 0, "Moving backwards in the filter?");
-+
-+  // Shift the buffer. We're just moving pointers here, so this is cheap.
-+  mLinesInBuffer -= diff;
-+  mLinesInBuffer = max(mLinesInBuffer, 0);
-+  for (int32_t i = 0; i < mLinesInBuffer; ++i) {
-+    swap(mWindow[i], mWindow[filterLength - mLinesInBuffer + i]);
-+  }
-+}
-+
-+
-+
-+} // namespace image
-+} // namespace mozilla
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch
deleted file mode 100644
index e01b5eaf2f..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1952-pt02.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/9719b71d72dd
-
-# HG changeset patch
-# User Byron Campen [:bwc] <docfaraday@gmail.com>
-# Date 1454100887 21600
-# Node ID 9719b71d72dd2a3c5ee12ace156af2a63d9595ac
-# Parent  b68673d974a10f65390f80b36d4307eb31e44669
-Bug 1234578 - Assert if PCM is destroyed improperly. r=rjesup, a=sylvestre
-
-diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
---- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
-+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
-@@ -712,16 +712,18 @@ PeerConnectionMedia::SelfDestruct_m()
- {
-   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
- 
-   ASSERT_ON_THREAD(mMainThread);
- 
-   mLocalSourceStreams.Clear();
-   mRemoteSourceStreams.Clear();
- 
-+  mMainThread = nullptr;
-+
-   // Final self-destruct.
-   this->Release();
- }
- 
- void
- PeerConnectionMedia::ShutdownMediaTransport_s()
- {
-   ASSERT_ON_THREAD(mSTSThread);
-diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
---- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
-+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
-@@ -210,17 +210,20 @@ class RemoteSourceStreamInfo : public So
-   std::vector<std::string> mTrackIdMap;
- 
-   // True iff SetPullEnabled(true) has been called on the DOMMediaStream. This
-   // happens when offer/answer concludes.
-   bool mReceiving;
- };
- 
- class PeerConnectionMedia : public sigslot::has_slots<> {
--  ~PeerConnectionMedia() {}
-+  ~PeerConnectionMedia()
-+  {
-+    MOZ_RELEASE_ASSERT(!mMainThread);
-+  }
- 
-  public:
-   explicit PeerConnectionMedia(PeerConnectionImpl *parent);
- 
-   PeerConnectionImpl* GetPC() { return mParent; }
-   nsresult Init(const std::vector<NrIceStunServer>& stun_servers,
-                 const std::vector<NrIceTurnServer>& turn_servers);
-   // WARNING: This destroys the object!
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch
deleted file mode 100644
index 96b83c118c..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1952-pt03.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/2839062f84fb
-
-# HG changeset patch
-# User Jan de Mooij <jdemooij@mozilla.com>
-# Date 1455119320 -3600
-# Node ID 2839062f84fb6cba2781ea8d59150f13d4813ddc
-# Parent  185b233ea03f3811404e3979b65ec86b29d13555
-Bug 1242279 - r=bhackett1024 a=sylvestre
-
-diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
---- a/js/src/vm/TypeInference.cpp
-+++ b/js/src/vm/TypeInference.cpp
-@@ -3961,16 +3961,22 @@ JSScript::maybeSweepTypes(AutoClearTypeI
- 
-     unsigned num = TypeScript::NumTypeSets(this);
-     StackTypeSet* typeArray = types_->typeArray();
- 
-     // Remove constraints and references to dead objects from stack type sets.
-     for (unsigned i = 0; i < num; i++)
-         typeArray[i].sweep(zone(), *oom);
- 
-+    if (oom->hadOOM()) {
-+        // It's possible we OOM'd while copying freeze constraints, so they
-+        // need to be regenerated.
-+        hasFreezeConstraints_ = false;
-+    }
-+
-     // Update the recompile indexes in any IonScripts still on the script.
-     if (hasIonScript())
-         ionScript()->recompileInfoRef().shouldSweep(types);
- }
- 
- void
- TypeScript::destroy()
- {
-diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h
---- a/js/src/vm/TypeInference.h
-+++ b/js/src/vm/TypeInference.h
-@@ -566,16 +566,19 @@ class AutoClearTypeInferenceStateOnOOM
-       : zone(zone), oom(false)
-     {}
- 
-     ~AutoClearTypeInferenceStateOnOOM();
- 
-     void setOOM() {
-         oom = true;
-     }
-+    bool hadOOM() const {
-+        return oom;
-+    }
- };
- 
- /* Superclass common to stack and heap type sets. */
- class ConstraintTypeSet : public TypeSet
- {
-   public:
-     /* Chain of constraints which propagate changes out from this type set. */
-     TypeConstraint* constraintList;
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch
deleted file mode 100644
index 4eeb2377b0..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1952-pt04.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/9dd60e798819
-
-# HG changeset patch
-# User Olli Pettay <bugs@pettay.fi>
-# Date 1455204078 -3600
-# Node ID 9dd60e798819fe2ebf1e5bd36aa9006ecd2f82c9
-# Parent  c1d67bd4c993b9e344c68954e6f0392c82b81e38
-Bug 1244250 - r=mats, a=al
-
-diff --git a/layout/style/nsAnimationManager.cpp b/layout/style/nsAnimationManager.cpp
---- a/layout/style/nsAnimationManager.cpp
-+++ b/layout/style/nsAnimationManager.cpp
-@@ -715,16 +715,17 @@ nsAnimationManager::FlushAnimations(Flus
-   }
- 
-   DispatchEvents(); // may destroy us
- }
- 
- void
- nsAnimationManager::DoDispatchEvents()
- {
-+  nsRefPtr<nsAnimationManager> kungFuDeathGrip(this);
-   EventArray events;
-   mPendingEvents.SwapElements(events);
-   for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) {
-     AnimationEventInfo &info = events[i];
-     EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
- 
-     if (!mPresContext) {
-       break;
-diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp
---- a/layout/style/nsTransitionManager.cpp
-+++ b/layout/style/nsTransitionManager.cpp
-@@ -753,16 +753,17 @@ nsTransitionManager::FlushTransitions(Fl
-       }
-     }
-   }
- 
-   if (didThrottle) {
-     mPresContext->Document()->SetNeedStyleFlush();
-   }
- 
-+  nsRefPtr<nsTransitionManager> kungFuDeathGrip(this);
-   for (uint32_t i = 0, i_end = events.Length(); i < i_end; ++i) {
-     TransitionEventInfo &info = events[i];
-     EventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
- 
-     if (!mPresContext) {
-       break;
-     }
-   }
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch
deleted file mode 100644
index d222feff2a..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1952-pt05.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/1dd0ca8e70bd
-
-# HG changeset patch
-# User Nicolas B. Pierron <nicolas.b.pierron@mozilla.com>
-# Date 1456161361 0
-# Node ID 1dd0ca8e70bd77b6fd93f36cc4e9c2cebfe8ba0a
-# Parent  95ff874886905ef46a7bbc760981d15ad0831096
-Bug 1221872 - ValueNumbering: Set the dominator index of fixup blocks when they are created. r=sunfish, a=ritu
-
-diff --git a/js/src/jit/ValueNumbering.cpp b/js/src/jit/ValueNumbering.cpp
---- a/js/src/jit/ValueNumbering.cpp
-+++ b/js/src/jit/ValueNumbering.cpp
-@@ -433,16 +433,17 @@ ValueNumberer::fixupOSROnlyLoop(MBasicBl
-     MBasicBlock* fake = MBasicBlock::NewAsmJS(graph_, block->info(),
-                                               nullptr, MBasicBlock::NORMAL);
-     if (fake == nullptr)
-         return false;
- 
-     graph_.insertBlockBefore(block, fake);
-     fake->setImmediateDominator(fake);
-     fake->addNumDominated(1);
-+    fake->setDomIndex(fake->id());
- 
-     // Create zero-input phis to use as inputs for any phis in |block|.
-     // Again, this is a little odd, but it's the least-odd thing we can do
-     // without significant complexity.
-     for (MPhiIterator iter(block->phisBegin()), end(block->phisEnd()); iter != end; ++iter) {
-         MPhi* phi = *iter;
-         MPhi* fakePhi = MPhi::New(graph_.alloc(), phi->type());
-         fake->addPhi(fakePhi);
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch b/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch
deleted file mode 100644
index 3de568493b..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1952-pt06.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/6f4d51302387
-
-# HG changeset patch
-# User Andrew McCreight <continuation@gmail.com>
-# Date 1456273423 28800
-# Node ID 6f4d5130238790fa5810c76ffeb9eccc65efa8c9
-# Parent  70f6c59d9d73a5edefd216b48ca74a931da12cf1
-Bug 1249685 - Use more nsCOMPtrs for stack variables in DOM code. r=smaug, a=ritu
-
-diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp
---- a/dom/base/nsRange.cpp
-+++ b/dom/base/nsRange.cpp
-@@ -1985,17 +1985,17 @@ nsRange::CutContents(DocumentFragment** 
-       rv = closestAncestor ? PrependChild(closestAncestor, nodeToResult)
-                            : PrependChild(commonCloneAncestor, nodeToResult);
-       NS_ENSURE_SUCCESS(rv, rv);
-       NS_ENSURE_STATE(!guard.Mutated(parent ? 2 : 1) ||
-                       ValidateCurrentNode(this, iter));
-     } else if (nodeToResult) {
-       nsMutationGuard guard;
-       nsCOMPtr<nsINode> node = nodeToResult;
--      nsINode* parent = node->GetParentNode();
-+      nsCOMPtr<nsINode> parent = node->GetParentNode();
-       if (parent) {
-         mozilla::ErrorResult error;
-         parent->RemoveChild(*node, error);
-         NS_ENSURE_FALSE(error.Failed(), error.ErrorCode());
-       }
-       NS_ENSURE_STATE(!guard.Mutated(1) ||
-                       ValidateCurrentNode(this, iter));
-     }
-diff --git a/dom/base/nsTreeSanitizer.cpp b/dom/base/nsTreeSanitizer.cpp
---- a/dom/base/nsTreeSanitizer.cpp
-+++ b/dom/base/nsTreeSanitizer.cpp
-@@ -1423,18 +1423,18 @@ nsTreeSanitizer::SanitizeChildren(nsINod
-                              mAllowStyles,
-                              false);
-         }
-         node = node->GetNextNonChildNode(aRoot);
-         continue;
-       }
-       if (MustFlatten(ns, localName)) {
-         RemoveAllAttributes(node);
--        nsIContent* next = node->GetNextNode(aRoot);
--        nsIContent* parent = node->GetParent();
-+        nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
-+        nsCOMPtr<nsIContent> parent = node->GetParent();
-         nsCOMPtr<nsIContent> child; // Must keep the child alive during move
-         ErrorResult rv;
-         while ((child = node->GetFirstChild())) {
-           parent->InsertBefore(*child, node, rv);
-           if (rv.Failed()) {
-             break;
-           }
-         }
-diff --git a/dom/html/HTMLSelectElement.cpp b/dom/html/HTMLSelectElement.cpp
---- a/dom/html/HTMLSelectElement.cpp
-+++ b/dom/html/HTMLSelectElement.cpp
-@@ -624,17 +624,17 @@ HTMLSelectElement::Add(nsGenericHTMLElem
- {
-   if (!aBefore) {
-     Element::AppendChild(aElement, aError);
-     return;
-   }
- 
-   // Just in case we're not the parent, get the parent of the reference
-   // element
--  nsINode* parent = aBefore->Element::GetParentNode();
-+  nsCOMPtr<nsINode> parent = aBefore->Element::GetParentNode();
-   if (!parent || !nsContentUtils::ContentIsDescendantOf(parent, this)) {
-     // NOT_FOUND_ERR: Raised if before is not a descendant of the SELECT
-     // element.
-     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
-     return;
-   }
- 
-   // If the before parameter is not null, we are equivalent to the
-diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp
---- a/dom/html/HTMLTableElement.cpp
-+++ b/dom/html/HTMLTableElement.cpp
-@@ -516,18 +516,18 @@ HTMLTableElement::InsertRow(int32_t aInd
-   if (rowCount > 0) {
-     if (refIndex == rowCount || aIndex == -1) {
-       // we set refIndex to the last row so we can get the last row's
-       // parent we then do an AppendChild below if (rowCount<aIndex)
- 
-       refIndex = rowCount - 1;
-     }
- 
--    Element* refRow = rows->Item(refIndex);
--    nsINode* parent = refRow->GetParentNode();
-+    RefPtr<Element> refRow = rows->Item(refIndex);
-+    nsCOMPtr<nsINode> parent = refRow->GetParentNode();
- 
-     // create the row
-     nsRefPtr<mozilla::dom::NodeInfo> nodeInfo;
-     nsContentUtils::NameChanged(mNodeInfo, nsGkAtoms::tr,
-                                 getter_AddRefs(nodeInfo));
- 
-     newRow = NS_NewHTMLTableRowElement(nodeInfo.forget());
- 
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1954.patch b/gnu/packages/patches/icecat-CVE-2016-1954.patch
deleted file mode 100644
index bbb4b3217c..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1954.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/a5c4c18849b4
-
-# HG changeset patch
-# User Christoph Kerschbaumer <mozilla@christophkerschbaumer.com>
-# Date 1456157874 28800
-# Node ID a5c4c18849b486ef8693e20421b69239a2cbe574
-# Parent  e93aeb25e2a44df8d22f5a065b4410620e2c8730
-Bug 1243178: CSP - Skip sending reports for non http schemes (r=dveditz) a=ritu
-
-diff --git a/dom/security/nsCSPContext.cpp b/dom/security/nsCSPContext.cpp
---- a/dom/security/nsCSPContext.cpp
-+++ b/dom/security/nsCSPContext.cpp
-@@ -798,16 +798,17 @@ nsCSPContext::SendReports(nsISupports* a
-       (NS_SUCCEEDED(reportURI->SchemeIs("https", &isHttpScheme)) && isHttpScheme);
- 
-     if (!isHttpScheme) {
-       const char16_t* params[] = { reportURIs[r].get() };
-       CSP_LogLocalizedStr(NS_LITERAL_STRING("reportURInotHttpsOrHttp2").get(),
-                           params, ArrayLength(params),
-                           aSourceFile, aScriptSample, aLineNum, 0,
-                           nsIScriptError::errorFlag, "CSP", mInnerWindowID);
-+      continue;
-     }
- 
-     // make sure this is an anonymous request (no cookies) so in case the
-     // policy URI is injected, it can't be abused for CSRF.
-     nsLoadFlags flags;
-     rv = reportChannel->GetLoadFlags(&flags);
-     NS_ENSURE_SUCCESS(rv, rv);
-     flags |= nsIRequest::LOAD_ANONYMOUS;
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1960.patch b/gnu/packages/patches/icecat-CVE-2016-1960.patch
deleted file mode 100644
index 6c5c885e8b..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1960.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/185b233ea03f
-
-# HG changeset patch
-# User Henri Sivonen <hsivonen@hsivonen.fi>
-# Date 1455100746 -7200
-# Node ID 185b233ea03f3811404e3979b65ec86b29d13555
-# Parent  271e3a5a53d96871141e89271f611033b512e3e4
-Bug 1246014. r=wchen. a=sylvestre
-
-diff --git a/parser/html/javasrc/TreeBuilder.java b/parser/html/javasrc/TreeBuilder.java
---- a/parser/html/javasrc/TreeBuilder.java
-+++ b/parser/html/javasrc/TreeBuilder.java
-@@ -4437,17 +4437,17 @@ public abstract class TreeBuilder<T> imp
-         return TreeBuilder.NOT_FOUND_ON_STACK;
-     }
- 
-     private void clearStackBackTo(int eltPos) throws SAXException {
-         int eltGroup = stack[eltPos].getGroup();
-         while (currentPtr > eltPos) { // > not >= intentional
-             if (stack[currentPtr].ns == "http://www.w3.org/1999/xhtml"
-                     && stack[currentPtr].getGroup() == TEMPLATE
--                    && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltGroup == HTML)) {
-+                    && (eltGroup == TABLE || eltGroup == TBODY_OR_THEAD_OR_TFOOT|| eltGroup == TR || eltPos == 0)) {
-                 return;
-             }
-             pop();
-         }
-     }
- 
-     private void resetTheInsertionMode() {
-         StackNode<T> node;
-diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp
---- a/parser/html/nsHtml5TreeBuilder.cpp
-+++ b/parser/html/nsHtml5TreeBuilder.cpp
-@@ -3301,17 +3301,17 @@ nsHtml5TreeBuilder::findLastInTableScope
-   return NS_HTML5TREE_BUILDER_NOT_FOUND_ON_STACK;
- }
- 
- void 
- nsHtml5TreeBuilder::clearStackBackTo(int32_t eltPos)
- {
-   int32_t eltGroup = stack[eltPos]->getGroup();
-   while (currentPtr > eltPos) {
--    if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE && (eltGroup == NS_HTML5TREE_BUILDER_TABLE || eltGroup == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || eltGroup == NS_HTML5TREE_BUILDER_TR || eltGroup == NS_HTML5TREE_BUILDER_HTML)) {
-+    if (stack[currentPtr]->ns == kNameSpaceID_XHTML && stack[currentPtr]->getGroup() == NS_HTML5TREE_BUILDER_TEMPLATE && (eltGroup == NS_HTML5TREE_BUILDER_TABLE || eltGroup == NS_HTML5TREE_BUILDER_TBODY_OR_THEAD_OR_TFOOT || eltGroup == NS_HTML5TREE_BUILDER_TR || !eltPos)) {
-       return;
-     }
-     pop();
-   }
- }
- 
- void 
- nsHtml5TreeBuilder::resetTheInsertionMode()
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1961.patch b/gnu/packages/patches/icecat-CVE-2016-1961.patch
deleted file mode 100644
index 10162be24b..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1961.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/e93aeb25e2a4
-
-# HG changeset patch
-# User Andrew McCreight <continuation@gmail.com>
-# Date 1455891967 28800
-# Node ID e93aeb25e2a44df8d22f5a065b4410620e2c8730
-# Parent  221de852fda32714a9e484774ceafafb450ea73c
-Bug 1249377 - Hold a strong reference to |root| in nsHTMLDocument::SetBody. r=bz, a=sylvestre
-
-diff --git a/dom/html/nsHTMLDocument.cpp b/dom/html/nsHTMLDocument.cpp
---- a/dom/html/nsHTMLDocument.cpp
-+++ b/dom/html/nsHTMLDocument.cpp
-@@ -1044,17 +1044,17 @@ nsHTMLDocument::SetBody(nsIDOMHTMLElemen
-   ErrorResult rv;
-   SetBody(static_cast<nsGenericHTMLElement*>(newBody.get()), rv);
-   return rv.ErrorCode();
- }
- 
- void
- nsHTMLDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv)
- {
--  Element* root = GetRootElement();
-+  nsCOMPtr<Element> root = GetRootElement();
- 
-   // The body element must be either a body tag or a frameset tag. And we must
-   // have a html root tag, otherwise GetBody will not return the newly set
-   // body.
-   if (!newBody || !(newBody->Tag() == nsGkAtoms::body ||
-                     newBody->Tag() == nsGkAtoms::frameset) ||
-       !root || !root->IsHTML() ||
-       root->Tag() != nsGkAtoms::html) {
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1962.patch b/gnu/packages/patches/icecat-CVE-2016-1962.patch
deleted file mode 100644
index 7eb4e072a1..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1962.patch
+++ /dev/null
@@ -1,107 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/221de852fda3
-
-# HG changeset patch
-# User Randell Jesup <rjesup@jesup.org>
-# Date 1455862087 18000
-# Node ID 221de852fda32714a9e484774ceafafb450ea73c
-# Parent  b03db72e32f6e3acdc9f8705371cb222d7e6c456
-Bug 1240760: Update DataChannel::Close() r=mcmanus, a=ritu
-
-MozReview-Commit-ID: 7nN9h3M3O8w
-
-diff --git a/netwerk/sctp/datachannel/DataChannel.cpp b/netwerk/sctp/datachannel/DataChannel.cpp
---- a/netwerk/sctp/datachannel/DataChannel.cpp
-+++ b/netwerk/sctp/datachannel/DataChannel.cpp
-@@ -1771,17 +1771,17 @@ DataChannelConnection::HandleStreamReset
-           }
-           NS_DispatchToMainThread(new DataChannelOnMessageAvailable(
-                                     DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED, this,
-                                     channel));
-           mStreams[channel->mStream] = nullptr;
- 
-           LOG(("Disconnected DataChannel %p from connection %p",
-                (void *) channel.get(), (void *) channel->mConnection.get()));
--          channel->Destroy();
-+          channel->DestroyLocked();
-           // At this point when we leave here, the object is a zombie held alive only by the DOM object
-         } else {
-           LOG(("Can't find incoming channel %d",i));
-         }
-       }
-     }
-   }
- 
-@@ -2498,17 +2498,17 @@ DataChannelConnection::CloseInt(DataChan
-       mStreams[channel->mStream] = nullptr;
-     } else {
-       SendOutgoingStreamReset();
-     }
-   }
-   aChannel->mState = CLOSING;
-   if (mState == CLOSED) {
-     // we're not going to hang around waiting
--    channel->Destroy();
-+    channel->DestroyLocked();
-   }
-   // At this point when we leave here, the object is a zombie held alive only by the DOM object
- }
- 
- void DataChannelConnection::CloseAll()
- {
-   LOG(("Closing all channels (connection %p)", (void*) this));
-   // Don't need to lock here
-@@ -2552,23 +2552,25 @@ DataChannel::~DataChannel()
-   // wrong, nothing bad happens.  A worst it's a leak.
-   NS_ASSERTION(mState == CLOSED || mState == CLOSING, "unexpected state in ~DataChannel");
- }
- 
- void
- DataChannel::Close()
- {
-   ENSURE_DATACONNECTION;
-+  RefPtr<DataChannelConnection> connection(mConnection);
-   mConnection->Close(this);
- }
- 
- // Used when disconnecting from the DataChannelConnection
- void
--DataChannel::Destroy()
-+DataChannel::DestroyLocked()
- {
-+  mConnection->mLock.AssertCurrentThreadOwns();
-   ENSURE_DATACONNECTION;
- 
-   LOG(("Destroying Data channel %u", mStream));
-   MOZ_ASSERT_IF(mStream != INVALID_STREAM,
-                 !mConnection->FindChannelByStream(mStream));
-   mStream = INVALID_STREAM;
-   mState = CLOSED;
-   mConnection = nullptr;
-diff --git a/netwerk/sctp/datachannel/DataChannel.h b/netwerk/sctp/datachannel/DataChannel.h
---- a/netwerk/sctp/datachannel/DataChannel.h
-+++ b/netwerk/sctp/datachannel/DataChannel.h
-@@ -331,19 +331,20 @@ public:
-     {
-       NS_ASSERTION(mConnection,"NULL connection");
-     }
- 
- private:
-   ~DataChannel();
- 
- public:
--  void Destroy(); // when we disconnect from the connection after stream RESET
-+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
- 
--  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
-+  // when we disconnect from the connection after stream RESET
-+  void DestroyLocked();
- 
-   // Close this DataChannel.  Can be called multiple times.  MUST be called
-   // before destroying the DataChannel (state must be CLOSED or CLOSING).
-   void Close();
- 
-   // Set the listener (especially for channels created from the other side)
-   void SetListener(DataChannelListener *aListener, nsISupports *aContext);
- 
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1964.patch b/gnu/packages/patches/icecat-CVE-2016-1964.patch
deleted file mode 100644
index e53fc749b5..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1964.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/a653013e7b50
-
-# HG changeset patch
-# User Peter Van der Beken <peterv@propagandism.org>
-# Date 1454340035 -3600
-# Node ID a653013e7b503912a32621e8da64a37171316588
-# Parent  0d0d7e8292f7ecf5f1149d528c0524f04447c4ad
-Bug 1243335 - report bad QName. r=sicking, a=sylvestre
-
-diff --git a/dom/xslt/xslt/txInstructions.cpp b/dom/xslt/xslt/txInstructions.cpp
---- a/dom/xslt/xslt/txInstructions.cpp
-+++ b/dom/xslt/xslt/txInstructions.cpp
-@@ -93,16 +93,19 @@ txAttribute::txAttribute(nsAutoPtr<Expr>
-                          txNamespaceMap* aMappings)
-     : mName(Move(aName)), mNamespace(Move(aNamespace)), mMappings(aMappings)
- {
- }
- 
- nsresult
- txAttribute::execute(txExecutionState& aEs)
- {
-+    nsAutoPtr<txTextHandler> handler(
-+        static_cast<txTextHandler*>(aEs.popResultHandler()));
-+
-     nsAutoString name;
-     nsresult rv = mName->evaluateToString(aEs.getEvalContext(), name);
-     NS_ENSURE_SUCCESS(rv, rv);
- 
-     const char16_t* colon;
-     if (!XMLUtils::isValidQName(name, &colon) ||
-         TX_StringEqualsAtom(name, nsGkAtoms::xmlns)) {
-         return NS_OK;
-@@ -125,19 +128,16 @@ txAttribute::execute(txExecutionState& a
-         if (!nspace.IsEmpty()) {
-             nsId = txNamespaceManager::getNamespaceID(nspace);
-         }
-     }
-     else if (colon) {
-         nsId = mMappings->lookupNamespace(prefix);
-     }
- 
--    nsAutoPtr<txTextHandler> handler(
--        static_cast<txTextHandler*>(aEs.popResultHandler()));
--
-     // add attribute if everything was ok
-     return nsId != kNameSpaceID_Unknown ?
-            aEs.mResultHandler->attribute(prefix, Substring(name, lnameStart),
-                                          nsId, handler->mValue) :
-            NS_OK;
- }
- 
- txCallTemplate::txCallTemplate(const txExpandedName& aName)
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1965.patch b/gnu/packages/patches/icecat-CVE-2016-1965.patch
deleted file mode 100644
index 8a37d4975c..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1965.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/b4467681abd6
-
-# HG changeset patch
-# User Gijs Kruitbosch <gijskruitbosch@gmail.com>
-# Date 1455276061 0
-# Node ID b4467681abd676cd5575cbdf922927f8f54d2ad9
-# Parent  8c1d40e45a72c6432e879137a0afa519dc6c9841
-Bug 1245264 - r=bz, r=ritu
-
-MozReview-Commit-ID: I0sVdritpD3
-
-diff --git a/dom/base/nsLocation.cpp b/dom/base/nsLocation.cpp
---- a/dom/base/nsLocation.cpp
-+++ b/dom/base/nsLocation.cpp
-@@ -735,16 +735,27 @@ nsLocation::SetProtocol(const nsAString&
-     return rv;
-   }
- 
-   rv = uri->SetScheme(NS_ConvertUTF16toUTF8(aProtocol));
-   if (NS_WARN_IF(NS_FAILED(rv))) {
-     return rv;
-   }
- 
-+  nsAutoCString newSpec;
-+  rv = uri->GetSpec(newSpec);
-+  if (NS_FAILED(rv)) {
-+    return rv;
-+  }
-+  // We may want a new URI class for the new URI, so recreate it:
-+  rv = NS_NewURI(getter_AddRefs(uri), newSpec);
-+  if (NS_FAILED(rv)) {
-+    return rv;
-+  }
-+
-   return SetURI(uri);
- }
- 
- void
- nsLocation::GetUsername(nsAString& aUsername, ErrorResult& aError)
- {
-   if (!CallerSubsumes()) {
-     aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1966.patch b/gnu/packages/patches/icecat-CVE-2016-1966.patch
deleted file mode 100644
index 6bf5f9f95e..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1966.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/291c2f31c48c
-
-# HG changeset patch
-# User Nicholas Nethercote <nnethercote@mozilla.com>
-# Date 1454650565 -39600
-# Node ID 291c2f31c48c7e96b1884b55273355970fa0fc30
-# Parent  11e6614756551cfd7291e73eefb90c52873a8480
-Bug 1246054 - Fix an erroneous nsNPObjWrapper assertion. r=froydnj. a=ritu
-
-diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp
---- a/dom/plugins/base/nsJSNPRuntime.cpp
-+++ b/dom/plugins/base/nsJSNPRuntime.cpp
-@@ -1915,18 +1915,19 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
-   // No existing JSObject, create one.
- 
-   JS::Rooted<JSObject*> obj(cx, ::JS_NewObject(cx, js::Jsvalify(&sNPObjectJSWrapperClass)));
- 
-   if (generation != sNPObjWrappers.Generation()) {
-       // Reload entry if the JS_NewObject call caused a GC and reallocated
-       // the table (see bug 445229). This is guaranteed to succeed.
- 
--      NS_ASSERTION(PL_DHashTableSearch(&sNPObjWrappers, npobj),
--                   "Hashtable didn't find what we just added?");
-+      entry = static_cast<NPObjWrapperHashEntry*>
-+        (PL_DHashTableSearch(&sNPObjWrappers, npobj));
-+      NS_ASSERTION(entry, "Hashtable didn't find what we just added?");
-   }
- 
-   if (!obj) {
-     // OOM? Remove the stale entry from the hash.
- 
-     PL_DHashTableRawRemove(&sNPObjWrappers, entry);
- 
-     return nullptr;
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-1974.patch b/gnu/packages/patches/icecat-CVE-2016-1974.patch
deleted file mode 100644
index 70fc23b8f3..0000000000
--- a/gnu/packages/patches/icecat-CVE-2016-1974.patch
+++ /dev/null
@@ -1,530 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/271e3a5a53d9
-
-# HG changeset patch
-# User Henri Sivonen <hsivonen@hsivonen.fi>
-# Date 1455014759 -7200
-# Node ID 271e3a5a53d96871141e89271f611033b512e3e4
-# Parent  9719b71d72dd2a3c5ee12ace156af2a63d9595ac
-Bug 1228103. r=smaug. a=sylvestre
-
-diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp
---- a/parser/htmlparser/nsExpatDriver.cpp
-+++ b/parser/htmlparser/nsExpatDriver.cpp
-@@ -1127,22 +1127,28 @@ nsExpatDriver::ConsumeToken(nsScanner& a
-       XML_Size lastLineLength = XML_GetCurrentColumnNumber(mExpatParser);
- 
-       if (lastLineLength <= consumed) {
-         // The length of the last line was less than what expat consumed, so
-         // there was at least one line break in the consumed data. Store the
-         // last line until the point where we stopped parsing.
-         nsScannerIterator startLastLine = currentExpatPosition;
-         startLastLine.advance(-((ptrdiff_t)lastLineLength));
--        CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine);
-+        if (!CopyUnicodeTo(startLastLine, currentExpatPosition, mLastLine)) {
-+          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
-+        }
-       }
-       else {
-         // There was no line break in the consumed data, append the consumed
-         // data.
--        AppendUnicodeTo(oldExpatPosition, currentExpatPosition, mLastLine);
-+        if (!AppendUnicodeTo(oldExpatPosition,
-+                             currentExpatPosition,
-+                             mLastLine)) {
-+          return (mInternalState = NS_ERROR_OUT_OF_MEMORY);
-+        }
-       }
-     }
- 
-     mExpatBuffered += length - consumed;
- 
-     if (BlockedOrInterrupted()) {
-       PR_LOG(GetExpatDriverLog(), PR_LOG_DEBUG,
-              ("Blocked or interrupted parser (probably for loading linked "
-diff --git a/parser/htmlparser/nsParser.cpp b/parser/htmlparser/nsParser.cpp
---- a/parser/htmlparser/nsParser.cpp
-+++ b/parser/htmlparser/nsParser.cpp
-@@ -1508,17 +1508,19 @@ nsParser::ResumeParse(bool allowIteratio
-                 DidBuildModel(mStreamStatus);
-                 return NS_OK;
-               }
-             } else {
-               CParserContext* theContext = PopContext();
-               if (theContext) {
-                 theIterationIsOk = allowIteration && theContextIsStringBased;
-                 if (theContext->mCopyUnused) {
--                  theContext->mScanner->CopyUnusedData(mUnusedInput);
-+                  if (!theContext->mScanner->CopyUnusedData(mUnusedInput)) {
-+                    mInternalState = NS_ERROR_OUT_OF_MEMORY;
-+                  }
-                 }
- 
-                 delete theContext;
-               }
- 
-               result = mInternalState;
-               aIsFinalChunk = mParserContext &&
-                               mParserContext->mStreamListenerState == eOnStop;
-diff --git a/parser/htmlparser/nsScanner.cpp b/parser/htmlparser/nsScanner.cpp
---- a/parser/htmlparser/nsScanner.cpp
-+++ b/parser/htmlparser/nsScanner.cpp
-@@ -379,17 +379,19 @@ nsresult nsScanner::Peek(nsAString& aStr
-   if (mCountRemaining < uint32_t(aNumChars + aOffset)) {
-     end = mEndPosition;
-   }
-   else {
-     end = start;
-     end.advance(aNumChars);
-   }
- 
--  CopyUnicodeTo(start, end, aStr);
-+  if (!CopyUnicodeTo(start, end, aStr)) {
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
- 
-   return NS_OK;
- }
- 
- 
- /**
-  *  Skip whitespace on scanner input stream
-  *  
-@@ -542,17 +544,19 @@ nsresult nsScanner::ReadTagIdentifier(ns
- 
-     if (!found) {
-       ++current;
-     }
-   }
- 
-   // Don't bother appending nothing.
-   if (current != mCurrentPosition) {
--    AppendUnicodeTo(mCurrentPosition, current, aString);
-+    if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
-+      return NS_ERROR_OUT_OF_MEMORY;
-+    }
-   }
- 
-   SetPosition(current);  
-   if (current == end) {
-     result = kEOF;
-   }
- 
-   //DoErrTest(aString);
-@@ -597,26 +601,30 @@ nsresult nsScanner::ReadEntityIdentifier
-         default:
-           found = ('a'<=theChar && theChar<='z') ||
-                   ('A'<=theChar && theChar<='Z') ||
-                   ('0'<=theChar && theChar<='9');
-           break;
-       }
- 
-       if(!found) {
--        AppendUnicodeTo(mCurrentPosition, current, aString);
-+        if (!AppendUnicodeTo(mCurrentPosition, current, aString)) {
-+          return NS_ERROR_OUT_OF_MEMORY;
-+        }
-         break;
-       }
-     }
-     ++current;
-   }
-   
-   SetPosition(current);
-   if (current == end) {
--    AppendUnicodeTo(origin, current, aString);
-+    if (!AppendUnicodeTo(origin, current, aString)) {
-+      return NS_ERROR_OUT_OF_MEMORY;
-+    }
-     return kEOF;
-   }
- 
-   //DoErrTest(aString);
- 
-   return result;
- }
- 
-@@ -646,26 +654,30 @@ nsresult nsScanner::ReadNumber(nsString&
-   while(current != end) {
-     theChar=*current;
-     if(theChar) {
-       done = (theChar < '0' || theChar > '9') && 
-              ((aBase == 16)? (theChar < 'A' || theChar > 'F') &&
-                              (theChar < 'a' || theChar > 'f')
-                              :true);
-       if(done) {
--        AppendUnicodeTo(origin, current, aString);
-+        if (!AppendUnicodeTo(origin, current, aString)) {
-+          return NS_ERROR_OUT_OF_MEMORY;
-+        }
-         break;
-       }
-     }
-     ++current;
-   }
- 
-   SetPosition(current);
-   if (current == end) {
--    AppendUnicodeTo(origin, current, aString);
-+    if (!AppendUnicodeTo(origin, current, aString)) {
-+      return NS_ERROR_OUT_OF_MEMORY;
-+    }
-     return kEOF;
-   }
- 
-   //DoErrTest(aString);
- 
-   return result;
- }
- 
-@@ -712,37 +724,43 @@ nsresult nsScanner::ReadWhitespace(nsSca
-           char16_t thePrevChar = theChar;
-           theChar = (++current != end) ? *current : '\0';
-           if ((thePrevChar == '\r' && theChar == '\n') ||
-               (thePrevChar == '\n' && theChar == '\r')) {
-             theChar = (++current != end) ? *current : '\0'; // CRLF == LFCR => LF
-             haveCR = true;
-           } else if (thePrevChar == '\r') {
-             // Lone CR becomes CRLF; callers should know to remove extra CRs
--            AppendUnicodeTo(origin, current, aString);
-+            if (!AppendUnicodeTo(origin, current, aString)) {
-+              return NS_ERROR_OUT_OF_MEMORY;
-+            }
-             aString.writable().Append(char16_t('\n'));
-             origin = current;
-             haveCR = true;
-           }
-         }
-         break;
-       case ' ' :
-       case '\t':
-         theChar = (++current != end) ? *current : '\0';
-         break;
-       default:
-         done = true;
--        AppendUnicodeTo(origin, current, aString);
-+        if (!AppendUnicodeTo(origin, current, aString)) {
-+          return NS_ERROR_OUT_OF_MEMORY;
-+        }
-         break;
-     }
-   }
- 
-   SetPosition(current);
-   if (current == end) {
--    AppendUnicodeTo(origin, current, aString);
-+    if (!AppendUnicodeTo(origin, current, aString)) {
-+      return NS_ERROR_OUT_OF_MEMORY;
-+    }
-     result = kEOF;
-   }
- 
-   aHaveCR = haveCR;
-   return result;
- }
- 
- //XXXbz callers of this have to manage their lone '\r' themselves if they want
-@@ -846,34 +864,38 @@ nsresult nsScanner::ReadUntil(nsAString&
-     if(!(theChar & aEndCondition.mFilter)) {
-       // They were. Do a thorough check.
- 
-       setcurrent = setstart;
-       while (*setcurrent) {
-         if (*setcurrent == theChar) {
-           if(addTerminal)
-             ++current;
--          AppendUnicodeTo(origin, current, aString);
-+          if (!AppendUnicodeTo(origin, current, aString)) {
-+            return NS_ERROR_OUT_OF_MEMORY;
-+          }
-           SetPosition(current);
- 
-           //DoErrTest(aString);
- 
-           return NS_OK;
-         }
-         ++setcurrent;
-       }
-     }
-     
-     ++current;
-   }
- 
-   // If we are here, we didn't find any terminator in the string and
-   // current = mEndPosition
-   SetPosition(current);
--  AppendUnicodeTo(origin, current, aString);
-+  if (!AppendUnicodeTo(origin, current, aString)) {
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-   return kEOF;
- }
- 
- nsresult nsScanner::ReadUntil(nsScannerSharedSubstring& aString,
-                               const nsReadEndCondition& aEndCondition,
-                               bool addTerminal)
- {  
-   if (!mSlidingBuffer) {
-@@ -906,34 +928,38 @@ nsresult nsScanner::ReadUntil(nsScannerS
-     if(!(theChar & aEndCondition.mFilter)) {
-       // They were. Do a thorough check.
- 
-       setcurrent = setstart;
-       while (*setcurrent) {
-         if (*setcurrent == theChar) {
-           if(addTerminal)
-             ++current;
--          AppendUnicodeTo(origin, current, aString);
-+          if (!AppendUnicodeTo(origin, current, aString)) {
-+            return NS_ERROR_OUT_OF_MEMORY;
-+          }
-           SetPosition(current);
- 
-           //DoErrTest(aString);
- 
-           return NS_OK;
-         }
-         ++setcurrent;
-       }
-     }
-     
-     ++current;
-   }
- 
-   // If we are here, we didn't find any terminator in the string and
-   // current = mEndPosition
-   SetPosition(current);
--  AppendUnicodeTo(origin, current, aString);
-+  if (!AppendUnicodeTo(origin, current, aString)) {
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-   return kEOF;
- }
- 
- nsresult nsScanner::ReadUntil(nsScannerIterator& aStart, 
-                               nsScannerIterator& aEnd,
-                               const nsReadEndCondition &aEndCondition,
-                               bool addTerminal)
- {
-@@ -1025,26 +1051,30 @@ nsresult nsScanner::ReadUntil(nsAString&
-     if (theChar == '\0') {
-       ReplaceCharacter(current, sInvalid);
-       theChar = sInvalid;
-     }
- 
-     if (aTerminalChar == theChar) {
-       if(addTerminal)
-         ++current;
--      AppendUnicodeTo(origin, current, aString);
-+      if (!AppendUnicodeTo(origin, current, aString)) {
-+        return NS_ERROR_OUT_OF_MEMORY;
-+      }
-       SetPosition(current);
-       return NS_OK;
-     }
-     ++current;
-   }
- 
-   // If we are here, we didn't find any terminator in the string and
-   // current = mEndPosition
--  AppendUnicodeTo(origin, current, aString);
-+  if (!AppendUnicodeTo(origin, current, aString)) {
-+    return NS_ERROR_OUT_OF_MEMORY;
-+  }
-   SetPosition(current);
-   return kEOF;
- 
- }
- 
- void nsScanner::BindSubstring(nsScannerSubstring& aSubstring, const nsScannerIterator& aStart, const nsScannerIterator& aEnd)
- {
-   aSubstring.Rebind(*mSlidingBuffer, aStart, aEnd);
-@@ -1142,29 +1172,29 @@ bool nsScanner::AppendToBuffer(nsScanner
- }
- 
- /**
-  *  call this to copy bytes out of the scanner that have not yet been consumed
-  *  by the tokenization process.
-  *  
-  *  @update  gess 5/12/98
-  *  @param   aCopyBuffer is where the scanner buffer will be copied to
-- *  @return  nada
-+ *  @return  true if OK or false on OOM
-  */
--void nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
-+bool nsScanner::CopyUnusedData(nsString& aCopyBuffer) {
-   if (!mSlidingBuffer) {
-     aCopyBuffer.Truncate();
--    return;
-+    return true;
-   }
- 
-   nsScannerIterator start, end;
-   start = mCurrentPosition;
-   end = mEndPosition;
- 
--  CopyUnicodeTo(start, end, aCopyBuffer);
-+  return CopyUnicodeTo(start, end, aCopyBuffer);
- }
- 
- /**
-  *  Retrieve the name of the file that the scanner is reading from.
-  *  In some cases, it's just a given name, because the scanner isn't
-  *  really reading from a file.
-  *  
-  *  @update  gess 5/12/98
-diff --git a/parser/htmlparser/nsScanner.h b/parser/htmlparser/nsScanner.h
---- a/parser/htmlparser/nsScanner.h
-+++ b/parser/htmlparser/nsScanner.h
-@@ -204,19 +204,19 @@ class nsScanner {
-                       nsIRequest *aRequest);
- 
-       /**
-        *  Call this to copy bytes out of the scanner that have not yet been consumed
-        *  by the tokenization process.
-        *  
-        *  @update  gess 5/12/98
-        *  @param   aCopyBuffer is where the scanner buffer will be copied to
--       *  @return  nada
-+       *  @return  true if OK or false on OOM
-        */
--      void CopyUnusedData(nsString& aCopyBuffer);
-+      bool CopyUnusedData(nsString& aCopyBuffer);
- 
-       /**
-        *  Retrieve the name of the file that the scanner is reading from.
-        *  In some cases, it's just a given name, because the scanner isn't
-        *  really reading from a file.
-        *  
-        *  @update  gess 5/12/98
-        *  @return  
-diff --git a/parser/htmlparser/nsScannerString.cpp b/parser/htmlparser/nsScannerString.cpp
---- a/parser/htmlparser/nsScannerString.cpp
-+++ b/parser/htmlparser/nsScannerString.cpp
-@@ -461,61 +461,63 @@ copy_multifragment_string( nsScannerIter
-         sink_traits::write(result, source_traits::read(first), distance);
-         NS_ASSERTION(distance > 0, "|copy_multifragment_string| will never terminate");
-         source_traits::advance(first, distance);
-       }
- 
-     return result;
-   }
- 
--void
-+bool
- CopyUnicodeTo( const nsScannerIterator& aSrcStart,
-                const nsScannerIterator& aSrcEnd,
-                nsAString& aDest )
-   {
-     nsAString::iterator writer;
-     if (!aDest.SetLength(Distance(aSrcStart, aSrcEnd), mozilla::fallible)) {
-       aDest.Truncate();
--      return; // out of memory
-+      return false; // out of memory
-     }
-     aDest.BeginWriting(writer);
-     nsScannerIterator fromBegin(aSrcStart);
-     
-     copy_multifragment_string(fromBegin, aSrcEnd, writer);
-+    return true;
-   }
- 
--void
-+bool
- AppendUnicodeTo( const nsScannerIterator& aSrcStart,
-                  const nsScannerIterator& aSrcEnd,
-                  nsScannerSharedSubstring& aDest )
-   {
-     // Check whether we can just create a dependent string.
-     if (aDest.str().IsEmpty()) {
-       // We can just make |aDest| point to the buffer.
-       // This will take care of copying if the buffer spans fragments.
-       aDest.Rebind(aSrcStart, aSrcEnd);
--    } else {
--      // The dest string is not empty, so it can't be a dependent substring.
--      AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
-+      return true;
-     }
-+    // The dest string is not empty, so it can't be a dependent substring.
-+    return AppendUnicodeTo(aSrcStart, aSrcEnd, aDest.writable());
-   }
- 
--void
-+bool
- AppendUnicodeTo( const nsScannerIterator& aSrcStart,
-                  const nsScannerIterator& aSrcEnd,
-                  nsAString& aDest )
-   {
-     nsAString::iterator writer;
-     uint32_t oldLength = aDest.Length();
-     if (!aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd), mozilla::fallible))
--      return; // out of memory
-+      return false; // out of memory
-     aDest.BeginWriting(writer).advance(oldLength);
-     nsScannerIterator fromBegin(aSrcStart);
-     
-     copy_multifragment_string(fromBegin, aSrcEnd, writer);
-+    return true;
-   }
- 
- bool
- FindCharInReadable( char16_t aChar,
-                     nsScannerIterator& aSearchStart,
-                     const nsScannerIterator& aSearchEnd )
-   {
-     while ( aSearchStart != aSearchEnd )
-diff --git a/parser/htmlparser/nsScannerString.h b/parser/htmlparser/nsScannerString.h
---- a/parser/htmlparser/nsScannerString.h
-+++ b/parser/htmlparser/nsScannerString.h
-@@ -539,43 +539,43 @@ nsScannerBufferList::Position::operator=
- inline
- size_t
- Distance( const nsScannerIterator& aStart, const nsScannerIterator& aEnd )
-   {
-     typedef nsScannerBufferList::Position Position;
-     return Position::Distance(Position(aStart), Position(aEnd));
-   }
- 
--void
-+bool
- CopyUnicodeTo( const nsScannerIterator& aSrcStart,
-                const nsScannerIterator& aSrcEnd,
-                nsAString& aDest );
- 
- inline
--void
-+bool
- CopyUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
-   {
-     nsScannerIterator begin, end;
--    CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
-+    return CopyUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
-   }
- 
--void
-+bool
- AppendUnicodeTo( const nsScannerIterator& aSrcStart,
-                  const nsScannerIterator& aSrcEnd,
-                  nsAString& aDest );
- 
- inline
--void
-+bool
- AppendUnicodeTo( const nsScannerSubstring& aSrc, nsAString& aDest )
-   {
-     nsScannerIterator begin, end;
--    AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
-+    return AppendUnicodeTo(aSrc.BeginReading(begin), aSrc.EndReading(end), aDest);
-   }
- 
--void
-+bool
- AppendUnicodeTo( const nsScannerIterator& aSrcStart,
-                  const nsScannerIterator& aSrcEnd,
-                  nsScannerSharedSubstring& aDest );
- 
- bool
- FindCharInReadable( char16_t aChar,
-                     nsScannerIterator& aStart,
-                     const nsScannerIterator& aEnd );
-
diff --git a/gnu/packages/patches/icecat-CVE-2016-2805.patch b/gnu/packages/patches/icecat-CVE-2016-2805.patch
new file mode 100644
index 0000000000..5e4150f00c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2805.patch
@@ -0,0 +1,75 @@
+Copied from https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/bf34b97757b3
+
+# HG changeset patch
+# User Jon Coppeard <jcoppeard@mozilla.com>
+# Date 1453890675 0
+# Node ID bf34b97757b334af1f9f53b9b59e0b6902e7ed6f
+# Parent  228ca3f46cabaf3f388f6c6640690772aa13c1a5
+Bug 1241731 - Handle incomplete buffer in DiscardTransferables r=sfink a=abillings a=sylvestre
+
+diff --git a/js/src/jit-test/tests/gc/bug-1241731.js b/js/src/jit-test/tests/gc/bug-1241731.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/gc/bug-1241731.js
+@@ -0,0 +1,4 @@
++if (!('oomTest' in this))
++    quit();
++
++oomTest(() => serialize(0, [{}]));
+diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp
+--- a/js/src/vm/StructuredClone.cpp
++++ b/js/src/vm/StructuredClone.cpp
+@@ -379,39 +379,50 @@ ReadStructuredClone(JSContext* cx, uint6
+ 
+ // If the given buffer contains Transferables, free them. Note that custom
+ // Transferables will use the JSStructuredCloneCallbacks::freeTransfer() to
+ // delete their transferables.
+ static void
+ Discard(uint64_t* buffer, size_t nbytes, const JSStructuredCloneCallbacks* cb, void* cbClosure)
+ {
+     MOZ_ASSERT(nbytes % sizeof(uint64_t) == 0);
+-    if (nbytes < sizeof(uint64_t))
++    uint64_t* end = buffer + nbytes / sizeof(uint64_t);
++    uint64_t* point = buffer;
++    if (point == end)
+         return; // Empty buffer
+ 
+-    uint64_t* point = buffer;
+     uint32_t tag, data;
+     SCInput::getPair(point++, &tag, &data);
+     if (tag != SCTAG_TRANSFER_MAP_HEADER)
+         return;
+ 
+     if (TransferableMapHeader(data) == SCTAG_TM_TRANSFERRED)
+         return;
+ 
+     // freeTransfer should not GC
+     JS::AutoSuppressGCAnalysis nogc;
+ 
++    if (point == end)
++        return;
++
+     uint64_t numTransferables = LittleEndian::readUint64(point++);
+     while (numTransferables--) {
++        if (point == end)
++            return;
++
+         uint32_t ownership;
+         SCInput::getPair(point++, &tag, &ownership);
+         MOZ_ASSERT(tag >= SCTAG_TRANSFER_MAP_PENDING_ENTRY);
++        if (point == end)
++            return;
+ 
+         void* content;
+         SCInput::getPtr(point++, &content);
++        if (point == end)
++            return;
+ 
+         uint64_t extraData = LittleEndian::readUint64(point++);
+ 
+         if (ownership < JS::SCTAG_TMO_FIRST_OWNED)
+             continue;
+ 
+         if (ownership == JS::SCTAG_TMO_ALLOC_DATA) {
+             js_free(content);
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-2807-pt1.patch b/gnu/packages/patches/icecat-CVE-2016-2807-pt1.patch
new file mode 100644
index 0000000000..0a6bee378b
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2807-pt1.patch
@@ -0,0 +1,35 @@
+Copied from https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/e7c23c08bf84
+
+# HG changeset patch
+# User Randell Jesup <rjesup@jesup.org>
+# Date 1458543433 14400
+# Node ID e7c23c08bf84a02d9154f31e0c5d121a45884a69
+# Parent  a6de1f453712edabff597879398606708c191098
+Bug 1254876: assert windows recording is shut down r=pkerr a=ritu
+
+MozReview-Commit-ID: JRqxBb5TgrE
+
+diff --git a/media/webrtc/trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc b/media/webrtc/trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc
+--- a/media/webrtc/trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc
++++ b/media/webrtc/trunk/webrtc/modules/audio_device/win/audio_device_core_win.cc
+@@ -567,16 +567,19 @@ AudioDeviceWindowsCore::AudioDeviceWindo
+ // ----------------------------------------------------------------------------
+ 
+ AudioDeviceWindowsCore::~AudioDeviceWindowsCore()
+ {
+     WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id, "%s destroyed", __FUNCTION__);
+ 
+     Terminate();
+ 
++    // Recording thread should be shut down before this!
++    assert(_hRecThread == NULL);
++
+     // The IMMDeviceEnumerator is created during construction. Must release
+     // it here and not in Terminate() since we don't recreate it in Init().
+     SAFE_RELEASE(_ptrEnumerator);
+ 
+     _ptrAudioBuffer = NULL;
+ 
+     if (NULL != _hRenderSamplesReadyEvent)
+     {
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-2807-pt2.patch b/gnu/packages/patches/icecat-CVE-2016-2807-pt2.patch
new file mode 100644
index 0000000000..f4b4c0d4eb
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2807-pt2.patch
@@ -0,0 +1,69 @@
+Copied from https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/3d2b62083a6a
+
+# HG changeset patch
+# User Shu-yu Guo <shu@rfrn.org>
+# Date 1459741387 -7200
+# Node ID 3d2b62083a6a4fb43cb330d77142f9dce0959a23
+# Parent  9d4364f6b55c6ee65c13c491292c3abe1ee2c993
+Bug 1254164 - Make aliasedBodyLevelLexicalBegin a uint32. r=Waldo, a=ritu
+
+diff --git a/js/src/jit-test/tests/parser/bug-1254164.js b/js/src/jit-test/tests/parser/bug-1254164.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/parser/bug-1254164.js
+@@ -0,0 +1,6 @@
++// |jit-test| slow;
++
++var s = '';
++for (var i = 0; i < 70000; i++)
++    s += 'function x' + i + '() { x' + i + '(); }\n';
++eval("(function() { " + s + " })();");
+diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp
+--- a/js/src/jsscript.cpp
++++ b/js/src/jsscript.cpp
+@@ -111,17 +111,20 @@ Bindings::initWithTemporaryStorage(Exclu
+     // JITs when interpreting/compiling aliasedvar ops.)
+ 
+     // Since unaliased variables are, by definition, only accessed by local
+     // operations and never through the scope chain, only give shapes to
+     // aliased variables. While the debugger may observe any scope object at
+     // any time, such accesses are mediated by DebugScopeProxy (see
+     // DebugScopeProxy::handleUnaliasedAccess).
+     uint32_t nslots = CallObject::RESERVED_SLOTS;
+-    uint32_t aliasedBodyLevelLexicalBegin = UINT16_MAX;
++
++    // Unless there are aliased body-level lexical bindings at all, set the
++    // begin index to an impossible slot number.
++    uint32_t aliasedBodyLevelLexicalBegin = LOCALNO_LIMIT;
+     for (BindingIter bi(self); bi; bi++) {
+         if (bi->aliased()) {
+             // Per ES6, lexical bindings cannot be accessed until
+             // initialized. Remember the first aliased slot that is a
+             // body-level lexical, so that they may be initialized to sentinel
+             // magic values.
+             if (numBodyLevelLexicals > 0 &&
+                 nslots < aliasedBodyLevelLexicalBegin &&
+diff --git a/js/src/jsscript.h b/js/src/jsscript.h
+--- a/js/src/jsscript.h
++++ b/js/src/jsscript.h
+@@ -201,18 +201,18 @@ class Bindings
+     friend class BindingIter;
+     friend class AliasedFormalIter;
+ 
+     RelocatablePtrShape callObjShape_;
+     uintptr_t bindingArrayAndFlag_;
+     uint16_t numArgs_;
+     uint16_t numBlockScoped_;
+     uint16_t numBodyLevelLexicals_;
+-    uint16_t aliasedBodyLevelLexicalBegin_;
+     uint16_t numUnaliasedBodyLevelLexicals_;
++    uint32_t aliasedBodyLevelLexicalBegin_;
+     uint32_t numVars_;
+     uint32_t numUnaliasedVars_;
+ 
+ #if JS_BITS_PER_WORD == 32
+     // Bindings is allocated inline inside JSScript, which needs to be
+     // gc::Cell aligned.
+     uint32_t padding_;
+ #endif
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-2807-pt3.patch b/gnu/packages/patches/icecat-CVE-2016-2807-pt3.patch
new file mode 100644
index 0000000000..a5a4212c28
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2807-pt3.patch
@@ -0,0 +1,33 @@
+Copied from https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/88f1eb2c3f4b
+
+# HG changeset patch
+# User Timothy Nikkel <tnikkel@gmail.com>
+# Date 1457637807 21600
+# Node ID 88f1eb2c3f4b4b57365ed88223cf8adc2bec4610
+# Parent  bf34b97757b334af1f9f53b9b59e0b6902e7ed6f
+Bug 1187420. r=drc r=jmuizelaar a=sylvestre
+
+MozReview-Commit-ID: Hh0Khqfj8Bf
+
+diff --git a/media/libjpeg/jstdhuff.c b/media/libjpeg/jstdhuff.c
+--- a/media/libjpeg/jstdhuff.c
++++ b/media/libjpeg/jstdhuff.c
+@@ -36,16 +36,17 @@ add_huff_table (j_common_ptr cinfo,
+    */
+   nsymbols = 0;
+   for (len = 1; len <= 16; len++)
+     nsymbols += bits[len];
+   if (nsymbols < 1 || nsymbols > 256)
+     ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ 
+   MEMCOPY((*htblptr)->huffval, val, nsymbols * sizeof(UINT8));
++  MEMZERO(&((*htblptr)->huffval[nsymbols]), (256 - nsymbols) * sizeof(UINT8));
+ 
+   /* Initialize sent_table FALSE so table will be written to JPEG file. */
+   (*htblptr)->sent_table = FALSE;
+ }
+ 
+ 
+ LOCAL(void)
+ std_huff_tables (j_common_ptr cinfo)
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-2807-pt4.patch b/gnu/packages/patches/icecat-CVE-2016-2807-pt4.patch
new file mode 100644
index 0000000000..5eff4fe99c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2807-pt4.patch
@@ -0,0 +1,37 @@
+Copied from https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/5c312182da90
+
+# HG changeset patch
+# User Jan de Mooij <jdemooij@mozilla.com>
+# Date 1458828581 -3600
+# Node ID 5c312182da9020504103aa329360abaffa7e232d
+# Parent  fa4efccde9b7efde8763a178a6cf422b6d37a0e9
+Bug 1254622 - Relookup group->newScript in CreateThisForFunctionWithGroup. r=bhackett a=sylvestre
+
+MozReview-Commit-ID: KXd7kB70f1Z
+
+diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp
+--- a/js/src/jsobj.cpp
++++ b/js/src/jsobj.cpp
+@@ -1574,18 +1574,19 @@ CreateThisForFunctionWithGroup(JSContext
+         // Not enough objects with this group have been created yet, so make a
+         // plain object and register it with the group. Use the maximum number
+         // of fixed slots, as is also required by the TypeNewScript.
+         gc::AllocKind allocKind = GuessObjectGCKind(NativeObject::MAX_FIXED_SLOTS);
+         PlainObject* res = NewObjectWithGroup<PlainObject>(cx, group, parent, allocKind, newKind);
+         if (!res)
+             return nullptr;
+ 
+-        if (newKind != SingletonObject)
+-            newScript->registerNewObject(res);
++        // Make sure group->newScript is still there.
++        if (newKind != SingletonObject && group->newScript())
++            group->newScript()->registerNewObject(res);
+ 
+         return res;
+     }
+ 
+     gc::AllocKind allocKind = NewObjectGCKind(&PlainObject::class_);
+ 
+     if (newKind == SingletonObject) {
+         Rooted<TaggedProto> protoRoot(cx, group->proto());
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-2807-pt5.patch b/gnu/packages/patches/icecat-CVE-2016-2807-pt5.patch
new file mode 100644
index 0000000000..00718ebaac
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2807-pt5.patch
@@ -0,0 +1,35 @@
+Copied from https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/3fdd280fa099
+
+# HG changeset patch
+# User Carsten "Tomcat" Book <cbook@mozilla.com>
+# Date 1461123938 -7200
+# Node ID 3fdd280fa099b6453ce9fd9905af883bc2ebce24
+# Parent  52dfdd37150d62f708dc5bf61dd28f3967596788
+Bug 1252707 - a=sylvestre
+
+diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp
+--- a/js/src/vm/Shape.cpp
++++ b/js/src/vm/Shape.cpp
+@@ -382,18 +382,20 @@ NativeObject::getChildPropertyOnDictiona
+ 
+     if (obj->inDictionaryMode()) {
+         MOZ_ASSERT(parent == obj->lastProperty());
+         RootedGeneric<StackShape*> childRoot(cx, &child);
+         shape = childRoot->isAccessorShape() ? NewGCAccessorShape(cx) : NewGCShape(cx);
+         if (!shape)
+             return nullptr;
+         if (childRoot->hasSlot() && childRoot->slot() >= obj->lastProperty()->base()->slotSpan()) {
+-            if (!obj->setSlotSpan(cx, childRoot->slot() + 1))
++            if (!obj->setSlotSpan(cx, childRoot->slot() + 1)) {
++                new (shape) Shape(obj->lastProperty()->base()->unowned(), 0);
+                 return nullptr;
++            }
+         }
+         shape->initDictionaryShape(*childRoot, obj->numFixedSlots(), &obj->shape_);
+     }
+ 
+     return shape;
+ }
+ 
+ /* static */ Shape*
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-2808.patch b/gnu/packages/patches/icecat-CVE-2016-2808.patch
new file mode 100644
index 0000000000..ae190b8b4c
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2808.patch
@@ -0,0 +1,389 @@
+Copied from https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/71f611fd27c7
+
+# HG changeset patch
+# User Jeff Walden <jwalden@mit.edu>
+# Date 1458941573 25200
+# Node ID 71f611fd27c7d6cb7d6dab9895c2922948042543
+# Parent  861f6b83ce1deade2a976cabe059776ad51ce370
+Bug 1246061.  r=luke, r=froydnj, a=sylvestre
+
+diff --git a/js/public/HashTable.h b/js/public/HashTable.h
+--- a/js/public/HashTable.h
++++ b/js/public/HashTable.h
+@@ -8,16 +8,17 @@
+ #define js_HashTable_h
+ 
+ #include "mozilla/Alignment.h"
+ #include "mozilla/Assertions.h"
+ #include "mozilla/Attributes.h"
+ #include "mozilla/Casting.h"
+ #include "mozilla/MemoryReporting.h"
+ #include "mozilla/Move.h"
++#include "mozilla/Opaque.h"
+ #include "mozilla/PodOperations.h"
+ #include "mozilla/ReentrancyGuard.h"
+ #include "mozilla/TemplateLib.h"
+ #include "mozilla/TypeTraits.h"
+ 
+ #include "js/Utility.h"
+ 
+ namespace js {
+@@ -27,16 +28,18 @@ template <class> struct DefaultHasher;
+ template <class, class> class HashMapEntry;
+ namespace detail {
+     template <class T> class HashTableEntry;
+     template <class T, class HashPolicy, class AllocPolicy> class HashTable;
+ }
+ 
+ /*****************************************************************************/
+ 
++using Generation = mozilla::Opaque<uint64_t>;
++
+ // A JS-friendly, STL-like container providing a hash-based map from keys to
+ // values. In particular, HashMap calls constructors and destructors of all
+ // objects added so non-PODs may be used safely.
+ //
+ // Key/Value requirements:
+ //  - movable, destructible, assignable
+ // HashPolicy requirements:
+ //  - see Hash Policy section below
+@@ -200,17 +203,19 @@ class HashMap
+         return impl.sizeOfExcludingThis(mallocSizeOf);
+     }
+     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+         return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
+     }
+ 
+     // If |generation()| is the same before and after a HashMap operation,
+     // pointers into the table remain valid.
+-    uint32_t generation() const                       { return impl.generation(); }
++    Generation generation() const {
++        return impl.generation();
++    }
+ 
+     /************************************************** Shorthand operations */
+ 
+     bool has(const Lookup& l) const {
+         return impl.lookup(l).found();
+     }
+ 
+     // Overwrite existing value with v. Return false on oom.
+@@ -431,17 +436,19 @@ class HashSet
+         return impl.sizeOfExcludingThis(mallocSizeOf);
+     }
+     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+         return mallocSizeOf(this) + impl.sizeOfExcludingThis(mallocSizeOf);
+     }
+ 
+     // If |generation()| is the same before and after a HashSet operation,
+     // pointers into the table remain valid.
+-    uint32_t generation() const                       { return impl.generation(); }
++    Generation generation() const {
++        return impl.generation();
++    }
+ 
+     /************************************************** Shorthand operations */
+ 
+     bool has(const Lookup& l) const {
+         return impl.lookup(l).found();
+     }
+ 
+     // Add |u| if it is not present already. Return false on oom.
+@@ -766,17 +773,17 @@ class HashTable : private AllocPolicy
+     // table operations unless |generation()| is tested.
+     class Ptr
+     {
+         friend class HashTable;
+ 
+         Entry* entry_;
+ #ifdef JS_DEBUG
+         const HashTable* table_;
+-        uint32_t generation;
++        Generation generation;
+ #endif
+ 
+       protected:
+         Ptr(Entry& entry, const HashTable& tableArg)
+           : entry_(&entry)
+ #ifdef JS_DEBUG
+           , table_(&tableArg)
+           , generation(tableArg.generation())
+@@ -873,17 +880,17 @@ class HashTable : private AllocPolicy
+             while (cur < end && !cur->isLive())
+                 ++cur;
+         }
+ 
+         Entry* cur, *end;
+ #ifdef JS_DEBUG
+         const HashTable* table_;
+         uint64_t mutationCount;
+-        uint32_t generation;
++        Generation generation;
+         bool validEntry;
+ #endif
+ 
+       public:
+         Range()
+           : cur(nullptr)
+           , end(nullptr)
+ #ifdef JS_DEBUG
+@@ -1012,18 +1019,18 @@ class HashTable : private AllocPolicy
+     // HashTable is not copyable or assignable
+     HashTable(const HashTable&) = delete;
+     void operator=(const HashTable&) = delete;
+ 
+   private:
+     static const size_t CAP_BITS = 24;
+ 
+   public:
+-    Entry*      table;                 // entry storage
+-    uint32_t    gen;                    // entry storage generation number
++    uint64_t    gen;                    // entry storage generation number
++    Entry*      table;                  // entry storage
+     uint32_t    entryCount;             // number of entries in table
+     uint32_t    removedCount:CAP_BITS;  // removed entry sentinels in table
+     uint32_t    hashShift:8;            // multiplicative hash shift
+ 
+ #ifdef JS_DEBUG
+     uint64_t     mutationCount;
+     mutable bool mEntered;
+     mutable struct Stats
+@@ -1097,18 +1104,18 @@ class HashTable : private AllocPolicy
+         for (Entry* e = oldTable, *end = e + capacity; e < end; ++e)
+             e->destroyIfLive();
+         alloc.free_(oldTable);
+     }
+ 
+   public:
+     explicit HashTable(AllocPolicy ap)
+       : AllocPolicy(ap)
++      , gen(0)
+       , table(nullptr)
+-      , gen(0)
+       , entryCount(0)
+       , removedCount(0)
+       , hashShift(sHashBits)
+ #ifdef JS_DEBUG
+       , mutationCount(0)
+       , mEntered(false)
+ #endif
+     {}
+@@ -1524,20 +1531,20 @@ class HashTable : private AllocPolicy
+     }
+ 
+     uint32_t capacity() const
+     {
+         MOZ_ASSERT(table);
+         return JS_BIT(sHashBits - hashShift);
+     }
+ 
+-    uint32_t generation() const
++    Generation generation() const
+     {
+         MOZ_ASSERT(table);
+-        return gen;
++        return Generation(gen);
+     }
+ 
+     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
+     {
+         return mallocSizeOf(table);
+     }
+ 
+     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
+diff --git a/js/src/jsapi.h b/js/src/jsapi.h
+--- a/js/src/jsapi.h
++++ b/js/src/jsapi.h
+@@ -270,20 +270,16 @@ class AutoHashMapRooter : protected Auto
+ 
+     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+         return map.sizeOfExcludingThis(mallocSizeOf);
+     }
+     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+         return map.sizeOfIncludingThis(mallocSizeOf);
+     }
+ 
+-    uint32_t generation() const {
+-        return map.generation();
+-    }
+-
+     /************************************************** Shorthand operations */
+ 
+     bool has(const Lookup& l) const {
+         return map.has(l);
+     }
+ 
+     template<typename KeyInput, typename ValueInput>
+     bool put(const KeyInput& k, const ValueInput& v) {
+@@ -385,20 +381,16 @@ class AutoHashSetRooter : protected Auto
+ 
+     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+         return set.sizeOfExcludingThis(mallocSizeOf);
+     }
+     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+         return set.sizeOfIncludingThis(mallocSizeOf);
+     }
+ 
+-    uint32_t generation() const {
+-        return set.generation();
+-    }
+-
+     /************************************************** Shorthand operations */
+ 
+     bool has(const Lookup& l) const {
+         return set.has(l);
+     }
+ 
+     bool put(const T& t) {
+         return set.put(t);
+diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h
+--- a/js/src/jscntxt.h
++++ b/js/src/jscntxt.h
+@@ -30,21 +30,21 @@ class DebugModeOSRVolatileJitFrameIterat
+ }
+ 
+ typedef HashSet<JSObject*> ObjectSet;
+ typedef HashSet<Shape*> ShapeSet;
+ 
+ /* Detects cycles when traversing an object graph. */
+ class AutoCycleDetector
+ {
++    Generation hashsetGenerationAtInit;
+     JSContext* cx;
+     RootedObject obj;
++    ObjectSet::AddPtr hashsetAddPointer;
+     bool cyclic;
+-    uint32_t hashsetGenerationAtInit;
+-    ObjectSet::AddPtr hashsetAddPointer;
+     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+ 
+   public:
+     AutoCycleDetector(JSContext* cx, HandleObject objArg
+                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+       : cx(cx), obj(cx, objArg), cyclic(true)
+     {
+         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp
+--- a/js/src/jswatchpoint.cpp
++++ b/js/src/jswatchpoint.cpp
+@@ -22,25 +22,25 @@ DefaultHasher<WatchKey>::hash(const Look
+ {
+     return DefaultHasher<JSObject*>::hash(key.object.get()) ^ HashId(key.id.get());
+ }
+ 
+ namespace {
+ 
+ class AutoEntryHolder {
+     typedef WatchpointMap::Map Map;
++    Generation gen;
+     Map& map;
+     Map::Ptr p;
+-    uint32_t gen;
+     RootedObject obj;
+     RootedId id;
+ 
+   public:
+     AutoEntryHolder(JSContext* cx, Map& map, Map::Ptr p)
+-      : map(map), p(p), gen(map.generation()), obj(cx, p->key().object), id(cx, p->key().id)
++      : gen(map.generation()), map(map), p(p), obj(cx, p->key().object), id(cx, p->key().id)
+     {
+         MOZ_ASSERT(!p->value().held);
+         p->value().held = true;
+     }
+ 
+     ~AutoEntryHolder() {
+         if (gen != map.generation())
+             p = map.lookup(WatchKey(obj, id));
+diff --git a/js/src/shell/jsheaptools.cpp b/js/src/shell/jsheaptools.cpp
+--- a/js/src/shell/jsheaptools.cpp
++++ b/js/src/shell/jsheaptools.cpp
+@@ -267,17 +267,17 @@ HeapReverser::traverseEdge(void* cell, J
+     Map::AddPtr a = map.lookupForAdd(cell);
+     if (!a) {
+         /*
+          * We've never visited this cell before. Add it to the map (thus
+          * marking it as visited), and put it on the work stack, to be
+          * visited from the main loop.
+          */
+         Node n(kind);
+-        uint32_t generation = map.generation();
++        Generation generation = map.generation();
+         if (!map.add(a, cell, Move(n)) ||
+             !work.append(Child(cell, kind)))
+             return false;
+         /* If the map has been resized, re-check the pointer. */
+         if (map.generation() != generation)
+             a = map.lookupForAdd(cell);
+     }
+ 
+diff --git a/mfbt/Opaque.h b/mfbt/Opaque.h
+new file mode 100644
+--- /dev/null
++++ b/mfbt/Opaque.h
+@@ -0,0 +1,44 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
++/* vim: set ts=8 sts=2 et sw=2 tw=80: */
++/* This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++/* An opaque integral type supporting only comparison operators. */
++
++#ifndef mozilla_Opaque_h
++#define mozilla_Opaque_h
++
++#include "mozilla/TypeTraits.h"
++
++namespace mozilla {
++
++/**
++ * Opaque<T> is a replacement for integral T in cases where only comparisons
++ * must be supported, and it's desirable to prevent accidental dependency on
++ * exact values.
++ */
++template<typename T>
++class Opaque final
++{
++  static_assert(mozilla::IsIntegral<T>::value,
++                "mozilla::Opaque only supports integral types");
++
++  T mValue;
++
++public:
++  Opaque() {}
++  explicit Opaque(T aValue) : mValue(aValue) {}
++
++  bool operator==(const Opaque& aOther) const {
++    return mValue == aOther.mValue;
++  }
++
++  bool operator!=(const Opaque& aOther) const {
++    return !(*this == aOther);
++  }
++};
++
++} // namespace mozilla
++
++#endif /* mozilla_Opaque_h */
+diff --git a/mfbt/moz.build b/mfbt/moz.build
+--- a/mfbt/moz.build
++++ b/mfbt/moz.build
+@@ -48,16 +48,17 @@ EXPORTS.mozilla = [
+     'MathAlgorithms.h',
+     'Maybe.h',
+     'MaybeOneOf.h',
+     'MemoryChecking.h',
+     'MemoryReporting.h',
+     'Move.h',
+     'NullPtr.h',
+     'NumericLimits.h',
++    'Opaque.h',
+     'Pair.h',
+     'PodOperations.h',
+     'Poison.h',
+     'Range.h',
+     'RangedPtr.h',
+     'RefCountType.h',
+     'ReentrancyGuard.h',
+     'RefPtr.h',
+
diff --git a/gnu/packages/patches/icecat-CVE-2016-2814.patch b/gnu/packages/patches/icecat-CVE-2016-2814.patch
new file mode 100644
index 0000000000..5f197f25e6
--- /dev/null
+++ b/gnu/packages/patches/icecat-CVE-2016-2814.patch
@@ -0,0 +1,35 @@
+
+# HG changeset patch
+# User Jean-Yves Avenard <jyavenard@mozilla.com>
+# Date 1460655260 25200
+# Node ID a13c0bc84d6eb132f4199f563fbe228d2d3b3a51
+# Parent  88f1eb2c3f4b4b57365ed88223cf8adc2bec4610
+Bug 1254721: Ensure consistency between Cenc offsets and sizes table. r=gerald a=sylvestre
+
+MozReview-Commit-ID: E1KbKIIBR87
+
+diff --git a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
+--- a/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
++++ b/media/libstagefright/frameworks/av/media/libstagefright/SampleTable.cpp
+@@ -612,18 +612,18 @@ status_t
+ SampleTable::parseSampleCencInfo() {
+     if ((!mCencDefaultSize && !mCencInfoCount) || mCencOffsets.isEmpty()) {
+         // We don't have all the cenc information we need yet. Quietly fail and
+         // hope we get the data we need later in the track header.
+         ALOGV("Got half of cenc saio/saiz pair. Deferring parse until we get the other half.");
+         return OK;
+     }
+ 
+-    if (!mCencSizes.isEmpty() && mCencOffsets.size() > 1 &&
+-        mCencSizes.size() != mCencOffsets.size()) {
++    if ((mCencOffsets.size() > 1 && mCencOffsets.size() < mCencInfoCount) ||
++        (!mCencDefaultSize && mCencSizes.size() < mCencInfoCount)) {
+         return ERROR_MALFORMED;
+     }
+ 
+     if (mCencInfoCount > kMAX_ALLOCATION / sizeof(SampleCencInfo)) {
+         // Avoid future OOM.
+         return ERROR_MALFORMED;
+     }
+ 
+
diff --git a/gnu/packages/patches/icecat-bug-1248851.patch b/gnu/packages/patches/icecat-bug-1248851.patch
deleted file mode 100644
index ea4d6831b5..0000000000
--- a/gnu/packages/patches/icecat-bug-1248851.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/8c1d40e45a72
-
-# HG changeset patch
-# User Xidorn Quan <quanxunzhen@gmail.com>
-# Date 1456199544 -28800
-# Node ID 8c1d40e45a72c6432e879137a0afa519dc6c9841
-# Parent  1dd0ca8e70bd77b6fd93f36cc4e9c2cebfe8ba0a
-Bug 1248851 - r=sicking, a=ritu
-
-diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp
---- a/dom/indexedDB/ActorsParent.cpp
-+++ b/dom/indexedDB/ActorsParent.cpp
-@@ -14823,22 +14823,19 @@ ObjectStoreAddOrPutRequestOp::DoDatabase
-     }
- 
-     snappy::RawCompress(uncompressed, uncompressedLength, compressed,
-                         &compressedLength);
- 
-     uint8_t* dataBuffer = reinterpret_cast<uint8_t*>(compressed);
-     size_t dataBufferLength = compressedLength;
- 
--    // If this call succeeds, | compressed | is now owned by the statement, and
--    // we are no longer responsible for it.
-     rv = stmt->BindAdoptedBlobByName(NS_LITERAL_CSTRING("data"), dataBuffer,
-                                      dataBufferLength);
-     if (NS_WARN_IF(NS_FAILED(rv))) {
--      moz_free(compressed);
-       return rv;
-     }
-   }
- 
-   nsCOMPtr<nsIFile> fileDirectory;
-   nsCOMPtr<nsIFile> journalDirectory;
- 
-   if (mFileManager) {
-
diff --git a/gnu/packages/patches/icecat-update-bundled-graphite2.patch b/gnu/packages/patches/icecat-update-bundled-graphite2.patch
new file mode 100644
index 0000000000..c3ab920335
--- /dev/null
+++ b/gnu/packages/patches/icecat-update-bundled-graphite2.patch
@@ -0,0 +1,2488 @@
+
+# HG changeset patch
+# User Jonathan Kew <jkew@mozilla.com>
+# Date 1460660890 -3600
+# Node ID 7330633d20ffb33941e41ea0666c4099b6e6d317
+# Parent  5c312182da9020504103aa329360abaffa7e232d
+Bug 1262846 (patch for ESR trees) - Update Graphite2 library to 1.3.8. r=jrmuizel a=sledru
+
+diff --git a/gfx/graphite2/README.mozilla b/gfx/graphite2/README.mozilla
+--- a/gfx/graphite2/README.mozilla
++++ b/gfx/graphite2/README.mozilla
+@@ -1,3 +1,3 @@
+-This directory contains the Graphite2 library release 1.3.6 from
+-https://github.com/silnrsi/graphite/releases/download/1.3.6/graphite-minimal-1.3.6.tgz
++This directory contains the Graphite2 library release 1.3.8 from
++https://github.com/silnrsi/graphite/releases/download/1.3.8/graphite2-minimal-1.3.8.tgz
+ See gfx/graphite2/moz-gr-update.sh for update procedure.
+diff --git a/gfx/graphite2/include/graphite2/Font.h b/gfx/graphite2/include/graphite2/Font.h
+--- a/gfx/graphite2/include/graphite2/Font.h
++++ b/gfx/graphite2/include/graphite2/Font.h
+@@ -25,17 +25,17 @@
+     either version 2 of the License or (at your option) any later version.
+ */
+ #pragma once
+ 
+ #include "graphite2/Types.h"
+ 
+ #define GR2_VERSION_MAJOR   1
+ #define GR2_VERSION_MINOR   3
+-#define GR2_VERSION_BUGFIX  6
++#define GR2_VERSION_BUGFIX  8
+ 
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+ 
+ typedef struct gr_face          gr_face;
+ typedef struct gr_font          gr_font;
+diff --git a/gfx/graphite2/moz-gr-update.sh b/gfx/graphite2/moz-gr-update.sh
+--- a/gfx/graphite2/moz-gr-update.sh
++++ b/gfx/graphite2/moz-gr-update.sh
+@@ -14,17 +14,17 @@
+ RELEASE=$1
+ 
+ if [ "x$RELEASE" == "x" ]
+ then
+     echo "Must provide the version number to be used."
+     exit 1
+ fi
+ 
+-TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite-minimal-$RELEASE.tgz"
++TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite2-minimal-$RELEASE.tgz"
+ 
+ foo=`basename $0`
+ TMPFILE=`mktemp -t ${foo}` || exit 1
+ 
+ curl -L "$TARBALL" -o "$TMPFILE"
+ tar -x -z -C gfx/graphite2/ --strip-components 1 -f "$TMPFILE" || exit 1
+ rm "$TMPFILE"
+ 
+diff --git a/gfx/graphite2/src/CachedFace.cpp b/gfx/graphite2/src/CachedFace.cpp
+--- a/gfx/graphite2/src/CachedFace.cpp
++++ b/gfx/graphite2/src/CachedFace.cpp
+@@ -64,20 +64,20 @@ bool CachedFace::runGraphite(Segment *se
+         return false;
+ 
+     assert(m_cacheStore);
+     // find where the segment can be broken
+     Slot * subSegStartSlot = seg->first();
+     Slot * subSegEndSlot = subSegStartSlot;
+     uint16 cmapGlyphs[eMaxSpliceSize];
+     int subSegStart = 0;
+-    for (unsigned int i = 0; i < seg->charInfoCount(); ++i)
++    for (unsigned int i = 0; i < seg->charInfoCount() && subSegEndSlot; ++i)
+     {
+         const unsigned int length = i - subSegStart + 1;
+-        if (length < eMaxSpliceSize)
++        if (length < eMaxSpliceSize && subSegEndSlot->gid() < m_cacheStore->maxCmapGid())
+             cmapGlyphs[length-1] = subSegEndSlot->gid();
+         else return false;
+         const bool spaceOnly = m_cacheStore->isSpaceGlyph(subSegEndSlot->gid());
+         // at this stage the character to slot mapping is still 1 to 1
+         const int   breakWeight = seg->charinfo(i)->breakWeight(),
+                     nextBreakWeight = (i + 1 < seg->charInfoCount())?
+                             seg->charinfo(i+1)->breakWeight() : 0;
+         const uint8 f = seg->charinfo(i)->flags();
+diff --git a/gfx/graphite2/src/Code.cpp b/gfx/graphite2/src/Code.cpp
+--- a/gfx/graphite2/src/Code.cpp
++++ b/gfx/graphite2/src/Code.cpp
+@@ -61,93 +61,88 @@ inline bool is_return(const instr i) {
+     const instr pop_ret  = *opmap[POP_RET].impl,
+                 ret_zero = *opmap[RET_ZERO].impl,
+                 ret_true = *opmap[RET_TRUE].impl;
+     return i == pop_ret || i == ret_zero || i == ret_true;
+ }
+ 
+ struct context
+ {
+-    context(uint8 ref=0) : codeRef(ref) {flags.changed=false; flags.referenced=false; flags.inserted=false;}
++    context(uint8 ref=0) : codeRef(ref) {flags.changed=false; flags.referenced=false;}
+     struct { 
+         uint8   changed:1,
+-                referenced:1,
+-                inserted:1;
++                referenced:1;
+     } flags;
+     uint8       codeRef;
+ };
+ 
+ } // end namespace
+ 
+ 
+ class Machine::Code::decoder
+ {
+ public:
+     struct limits;
+-    struct analysis
+-    {
+-        static const int NUMCONTEXTS = 256;
+-        uint8     slotref;
+-        context   contexts[NUMCONTEXTS];
+-        byte      max_ref;
+-        
+-        analysis() : slotref(0), max_ref(0) {};
+-        void set_ref(int index, bool incinsert=false) throw();
+-        void set_noref(int index) throw();
+-        void set_changed(int index) throw();
+-
+-    };
++    static const int NUMCONTEXTS = 256;
+     
+     decoder(limits & lims, Code &code, enum passtype pt) throw();
+     
+     bool        load(const byte * bc_begin, const byte * bc_end);
+     void        apply_analysis(instr * const code, instr * code_end);
+-    byte        max_ref() { return _analysis.max_ref; }
+-    int         pre_context() const { return _pre_context; }
++    byte        max_ref() { return _max_ref; }
++    int         out_index() const { return _out_index; }
+     
+ private:
++    void        set_ref(int index) throw();
++    void        set_noref(int index) throw();
++    void        set_changed(int index) throw();
+     opcode      fetch_opcode(const byte * bc);
+     void        analyse_opcode(const opcode, const int8 * const dp) throw();
+     bool        emit_opcode(opcode opc, const byte * & bc);
+-    bool        validate_opcode(const opcode opc, const byte * const bc);
++    bool        validate_opcode(const byte opc, const byte * const bc);
+     bool        valid_upto(const uint16 limit, const uint16 x) const throw();
+     bool        test_context() const throw();
++    bool        test_ref(int8 index) const throw();
+     void        failure(const status_t s) const throw() { _code.failure(s); }
+     
+     Code              & _code;
+-    int                 _pre_context;
+-    uint16              _rule_length;
++    int                 _out_index;
++    uint16              _out_length;
+     instr             * _instr;
+     byte              * _data;
+     limits            & _max;
+-    analysis            _analysis;
+     enum passtype       _passtype;
+     int                 _stack_depth;
+     bool                _in_ctxt_item;
++    int16               _slotref;
++    context             _contexts[NUMCONTEXTS];
++    byte                _max_ref;
+ };
+ 
+ 
+ struct Machine::Code::decoder::limits
+ {
+   const byte       * bytecode;
+   const uint8        pre_context;
+   const uint16       rule_length,
+                      classes,
+                      glyf_attrs,
+                      features;
+   const byte         attrid[gr_slatMax];
+ };
+    
+ inline Machine::Code::decoder::decoder(limits & lims, Code &code, enum passtype pt) throw()
+ : _code(code),
+-  _pre_context(code._constraint ? 0 : lims.pre_context), 
+-  _rule_length(code._constraint ? 1 : lims.rule_length), 
++  _out_index(code._constraint ? 0 : lims.pre_context), 
++  _out_length(code._constraint ? 1 : lims.rule_length), 
+   _instr(code._code), _data(code._data), _max(lims), _passtype(pt),
+   _stack_depth(0),
+-  _in_ctxt_item(false)
++  _in_ctxt_item(false),
++  _slotref(0),
++  _max_ref(0)
+ { }
+     
+ 
+ 
+ Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
+            uint8 pre_context, uint16 rule_length, const Silf & silf, const Face & face,
+            enum passtype pt, byte * * const _out)
+  :  _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0), _status(loaded),
+@@ -163,17 +158,17 @@ Machine::Code::Code(bool is_constraint, 
+       return;
+     }
+     assert(bytecode_end > bytecode_begin);
+     const opcode_t *    op_to_fn = Machine::getOpcodeTable();
+     
+     // Allocate code and data target buffers, these sizes are a worst case
+     // estimate.  Once we know their real sizes the we'll shrink them.
+     if (_out)   _code = reinterpret_cast<instr *>(*_out);
+-    else        _code = static_cast<instr *>(malloc(estimateCodeDataOut(bytecode_end-bytecode_begin)));
++    else        _code = static_cast<instr *>(malloc(estimateCodeDataOut(bytecode_end-bytecode_begin, 1, is_constraint ? 0 : rule_length)));
+     _data = reinterpret_cast<byte *>(_code + (bytecode_end - bytecode_begin));
+     
+     if (!_code || !_data) {
+         failure(alloc_failed);
+         return;
+     }
+     
+     decoder::limits lims = {
+@@ -266,23 +261,23 @@ bool Machine::Code::decoder::load(const 
+     return bool(_code);
+ }
+ 
+ // Validation check and fixups.
+ //
+ 
+ opcode Machine::Code::decoder::fetch_opcode(const byte * bc)
+ {
+-    const opcode opc = opcode(*bc++);
++    const byte opc = *bc++;
+ 
+     // Do some basic sanity checks based on what we know about the opcode
+     if (!validate_opcode(opc, bc))  return MAX_OPCODE;
+ 
+     // And check it's arguments as far as possible
+-    switch (opc)
++    switch (opcode(opc))
+     {
+         case NOP :
+             break;
+         case PUSH_BYTE :
+         case PUSH_BYTEU :
+         case PUSH_SHORT :
+         case PUSH_SHORTU :
+         case PUSH_LONG :
+@@ -319,47 +314,57 @@ opcode Machine::Code::decoder::fetch_opc
+         case COND :
+             _stack_depth -= 2;
+             if (_stack_depth <= 0)
+                 failure(underfull_stack);
+             break;
+         case NEXT :
+         case NEXT_N :           // runtime checked
+         case COPY_NEXT :
+-            test_context();
+-            ++_pre_context;
++            ++_out_index;
++            if (_out_index < -1 || _out_index > _out_length || _slotref > _max.rule_length)
++                failure(out_of_range_data);
+             break;
+         case PUT_GLYPH_8BIT_OBS :
+             valid_upto(_max.classes, bc[0]);
+             test_context();
+             break;
+         case PUT_SUBS_8BIT_OBS :
+-            valid_upto(_rule_length, _pre_context + int8(bc[0]));
++            test_ref(int8(bc[0]));
+             valid_upto(_max.classes, bc[1]);
+             valid_upto(_max.classes, bc[2]);
+             test_context();
+             break;
+         case PUT_COPY :
+-            valid_upto(_rule_length, _pre_context + int8(bc[0]));
++            test_ref(int8(bc[0]));
+             test_context();
+             break;
+         case INSERT :
+             if (_passtype >= PASS_TYPE_POSITIONING)
+                 failure(invalid_opcode);
+-            else
+-                --_pre_context;
++            ++_out_length;
++            if (_out_index < 0) ++_out_index;
++            if (_out_index < -1 || _out_index >= _out_length)
++                failure(out_of_range_data);
+             break;
+         case DELETE :
+             if (_passtype >= PASS_TYPE_POSITIONING)
+                 failure(invalid_opcode);
+-            test_context();
++            if (_out_index < _max.pre_context)
++                failure(out_of_range_data);
++            --_out_index;
++            --_out_length;
++            if (_out_index < -1 || _out_index > _out_length)
++                failure(out_of_range_data);
+             break;
+         case ASSOC :
++            if (bc[0] == 0)
++                failure(out_of_range_data);
+             for (uint8 num = bc[0]; num; --num)
+-                valid_upto(_rule_length, _pre_context + int8(bc[num]));
++                test_ref(int8(bc[num]));
+             test_context();
+             break;
+         case CNTXT_ITEM :
+             valid_upto(_max.rule_length, _max.pre_context + int8(bc[0]));
+             if (bc + 2 + bc[1] >= _max.bytecode)    failure(jump_past_end);
+             if (_in_ctxt_item)                      failure(nested_context_item);
+             break;
+         case ATTR_SET :
+@@ -378,52 +383,43 @@ opcode Machine::Code::decoder::fetch_opc
+                 failure(underfull_stack);
+             if (valid_upto(gr_slatMax, bc[0]))
+                 valid_upto(_max.attrid[bc[0]], bc[1]);
+             test_context();
+             break;
+         case PUSH_SLOT_ATTR :
+             ++_stack_depth;
+             valid_upto(gr_slatMax, bc[0]);
+-            valid_upto(_rule_length, _pre_context + int8(bc[1]));
++            test_ref(int8(bc[1]));
+             if (attrCode(bc[0]) == gr_slatUserDefn)     // use IATTR for user attributes
+                 failure(out_of_range_data);
+             break;
+         case PUSH_GLYPH_ATTR_OBS :
++        case PUSH_ATT_TO_GATTR_OBS :
+             ++_stack_depth;
+             valid_upto(_max.glyf_attrs, bc[0]);
+-            valid_upto(_rule_length, _pre_context + int8(bc[1]));
++            test_ref(int8(bc[1]));
+             break;
++        case PUSH_ATT_TO_GLYPH_METRIC :
+         case PUSH_GLYPH_METRIC :
+             ++_stack_depth;
+             valid_upto(kgmetDescent, bc[0]);
+-            valid_upto(_rule_length, _pre_context + int8(bc[1]));
++            test_ref(int8(bc[1]));
+             // level: dp[2] no check necessary
+             break;
+         case PUSH_FEAT :
+             ++_stack_depth;
+             valid_upto(_max.features, bc[0]);
+-            valid_upto(_rule_length, _pre_context + int8(bc[1]));
+-            break;
+-        case PUSH_ATT_TO_GATTR_OBS :
+-            ++_stack_depth;
+-            valid_upto(_max.glyf_attrs, bc[0]);
+-            valid_upto(_rule_length, _pre_context + int8(bc[1]));
+-            break;
+-        case PUSH_ATT_TO_GLYPH_METRIC :
+-            ++_stack_depth;
+-            valid_upto(kgmetDescent, bc[0]);
+-            valid_upto(_rule_length, _pre_context + int8(bc[1]));
+-            // level: dp[2] no check necessary
++            test_ref(int8(bc[1]));
+             break;
+         case PUSH_ISLOT_ATTR :
+             ++_stack_depth;
+             if (valid_upto(gr_slatMax, bc[0]))
+             {
+-                valid_upto(_rule_length, _pre_context + int8(bc[1]));
++                test_ref(int8(bc[1]));
+                 valid_upto(_max.attrid[bc[0]], bc[2]);
+             }
+             break;
+         case PUSH_IGLYPH_ATTR :// not implemented
+             ++_stack_depth;
+             break;
+         case POP_RET :
+             if (--_stack_depth < 0)
+@@ -442,118 +438,107 @@ opcode Machine::Code::decoder::fetch_opc
+                 valid_upto(_max.attrid[bc[0]], bc[1]);
+             test_context();
+             break;
+         case PUSH_PROC_STATE :  // dummy: dp[0] no check necessary
+         case PUSH_VERSION :
+             ++_stack_depth;
+             break;
+         case PUT_SUBS :
+-            valid_upto(_rule_length, _pre_context + int8(bc[0]));
++            test_ref(int8(bc[0]));
+             valid_upto(_max.classes, uint16(bc[1]<< 8) | bc[2]);
+             valid_upto(_max.classes, uint16(bc[3]<< 8) | bc[4]);
+             test_context();
+             break;
+         case PUT_SUBS2 :        // not implemented
+         case PUT_SUBS3 :        // not implemented
+             break;
+         case PUT_GLYPH :
+             valid_upto(_max.classes, uint16(bc[0]<< 8) | bc[1]);
+             test_context();
+             break;
+         case PUSH_GLYPH_ATTR :
+         case PUSH_ATT_TO_GLYPH_ATTR :
+             ++_stack_depth;
+             valid_upto(_max.glyf_attrs, uint16(bc[0]<< 8) | bc[1]);
+-            valid_upto(_rule_length, _pre_context + int8(bc[2]));
++            test_ref(int8(bc[2]));
++            break;
++        case SET_FEAT :
++            valid_upto(_max.features, bc[0]);
++            test_ref(int8(bc[1]));
+             break;
+         default:
+             failure(invalid_opcode);
+             break;
+     }
+ 
+-    return bool(_code) ? opc : MAX_OPCODE;
++    return bool(_code) ? opcode(opc) : MAX_OPCODE;
+ }
+ 
+ 
+ void Machine::Code::decoder::analyse_opcode(const opcode opc, const int8  * arg) throw()
+ {
+-  if (_code._constraint) return;
+-  
+   switch (opc)
+   {
+     case DELETE :
+       _code._delete = true;
+       break;
++    case ASSOC :
++      set_changed(0);
++//      for (uint8 num = arg[0]; num; --num)
++//        _analysis.set_noref(num);
++      break;
+     case PUT_GLYPH_8BIT_OBS :
+     case PUT_GLYPH :
+       _code._modify = true;
+-      _analysis.set_changed(0);
++      set_changed(0);
+       break;
+     case ATTR_SET :
+     case ATTR_ADD :
++    case ATTR_SUB :
+     case ATTR_SET_SLOT :
+     case IATTR_SET_SLOT :
+     case IATTR_SET :
+     case IATTR_ADD :
+     case IATTR_SUB :
+-      _analysis.set_noref(0);
++      set_noref(0);
+       break;
+     case NEXT :
+     case COPY_NEXT :
+-      if (!_analysis.contexts[_analysis.slotref].flags.inserted)
+-        ++_analysis.slotref;
+-      _analysis.contexts[_analysis.slotref] = context(_code._instr_count+1);
++      ++_slotref;
++      _contexts[_slotref] = context(_code._instr_count+1);
+       // if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref;
+       break;
+     case INSERT :
+-      _analysis.contexts[_analysis.slotref].flags.inserted = true;
++      if (_slotref >= 0) --_slotref;
+       _code._modify = true;
+       break;
+     case PUT_SUBS_8BIT_OBS :    // slotref on 1st parameter
+     case PUT_SUBS : 
+       _code._modify = true;
+-      _analysis.set_changed(0);
++      set_changed(0);
+       GR_FALLTHROUGH;
+       // no break
+     case PUT_COPY :
+-    {
+-      if (arg[0] != 0) { _analysis.set_changed(0); _code._modify = true; }
+-      if (arg[0] <= 0 && -arg[0] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
+-        _analysis.set_ref(arg[0], true);
+-      else if (arg[0] > 0)
+-        _analysis.set_ref(arg[0], true);
++      if (arg[0] != 0) { set_changed(0); _code._modify = true; }
++      set_ref(arg[0]);
+       break;
+-    }
+-    case PUSH_ATT_TO_GATTR_OBS : // slotref on 2nd parameter
+-        if (_code._constraint) return;
+-        GR_FALLTHROUGH;
+-        // no break
+     case PUSH_GLYPH_ATTR_OBS :
+     case PUSH_SLOT_ATTR :
+     case PUSH_GLYPH_METRIC :
++    case PUSH_ATT_TO_GATTR_OBS :
+     case PUSH_ATT_TO_GLYPH_METRIC :
+     case PUSH_ISLOT_ATTR :
+     case PUSH_FEAT :
+-      if (arg[1] <= 0 && -arg[1] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
+-        _analysis.set_ref(arg[1], true);
+-      else if (arg[1] > 0)
+-        _analysis.set_ref(arg[1], true);
++    case SET_FEAT :
++      set_ref(arg[1]);
+       break;
+     case PUSH_ATT_TO_GLYPH_ATTR :
+-        if (_code._constraint) return;
+-        GR_FALLTHROUGH;
+-        // no break
+     case PUSH_GLYPH_ATTR :
+-      if (arg[2] <= 0 && -arg[2] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
+-        _analysis.set_ref(arg[2], true);
+-      else if (arg[2] > 0)
+-        _analysis.set_ref(arg[2], true);
+-      break;
+-    case ASSOC :                // slotrefs in varargs
++      set_ref(arg[2]);
+       break;
+     default:
+         break;
+   }
+ }
+ 
+ 
+ bool Machine::Code::decoder::emit_opcode(opcode opc, const byte * & bc)
+@@ -579,81 +564,89 @@ bool Machine::Code::decoder::emit_opcode
+         _data            += param_sz;
+         _code._data_size += param_sz;
+     }
+     
+     // recursively decode a context item so we can split the skip into 
+     // instruction and data portions.
+     if (opc == CNTXT_ITEM)
+     {
+-        assert(_pre_context == 0);
++        assert(_out_index == 0);
+         _in_ctxt_item = true;
+-        _pre_context = _max.pre_context + int8(_data[-2]);
+-        _rule_length = _max.rule_length;
++        _out_index = _max.pre_context + int8(_data[-2]);
++        _slotref = int8(_data[-2]);
++        _out_length = _max.rule_length;
+ 
+         const size_t ctxt_start = _code._instr_count;
+         byte & instr_skip = _data[-1];
+         byte & data_skip  = *_data++;
+         ++_code._data_size;
+         const byte *curr_end = _max.bytecode;
+ 
+         if (load(bc, bc + instr_skip))
+         {
+             bc += instr_skip;
+             data_skip  = instr_skip - (_code._instr_count - ctxt_start);
+             instr_skip = _code._instr_count - ctxt_start;
+             _max.bytecode = curr_end;
+ 
+-            _rule_length = 1;
+-            _pre_context = 0;
++            _out_length = 1;
++            _out_index = 0;
++            _slotref = 0;
+             _in_ctxt_item = false;
+         }
+         else
+         {
+-            _pre_context = 0;
++            _out_index = 0;
++            _slotref = 0;
+             return false;
+         }
+     }
+     
+     return bool(_code);
+ }
+ 
+ 
+ void Machine::Code::decoder::apply_analysis(instr * const code, instr * code_end)
+ {
+     // insert TEMP_COPY commands for slots that need them (that change and are referenced later)
+     int tempcount = 0;
+     if (_code._constraint) return;
+ 
+     const instr temp_copy = Machine::getOpcodeTable()[TEMP_COPY].impl[0];
+-    for (const context * c = _analysis.contexts, * const ce = c + _analysis.slotref; c != ce; ++c)
++    for (const context * c = _contexts, * const ce = c + _slotref; c < ce; ++c)
+     {
+         if (!c->flags.referenced || !c->flags.changed) continue;
+         
+         instr * const tip = code + c->codeRef + tempcount;        
+         memmove(tip+1, tip, (code_end - tip) * sizeof(instr));
+         *tip = temp_copy;
+         ++code_end;
+         ++tempcount;
+         _code._delete = true;
+     }
+     
+     _code._instr_count = code_end - code;
+ }
+ 
+ 
+ inline
+-bool Machine::Code::decoder::validate_opcode(const opcode opc, const byte * const bc)
++bool Machine::Code::decoder::validate_opcode(const byte opc, const byte * const bc)
+ {
+     if (opc >= MAX_OPCODE)
+     {
+         failure(invalid_opcode);
+         return false;
+     }
+     const opcode_t & op = Machine::getOpcodeTable()[opc];
++    if (op.impl[_code._constraint] == 0)
++    {
++        failure(unimplemented_opcode_used);
++        return false;
++    }
+     if (op.param_sz == VARARGS && bc >= _max.bytecode)
+     {
+         failure(arguments_exhausted);
+         return false;
+     }
+     const size_t param_sz = op.param_sz == VARARGS ? bc[0] + 1 : op.param_sz;
+     if (bc - 1 + param_sz >= _max.bytecode)
+     {
+@@ -666,56 +659,69 @@ bool Machine::Code::decoder::validate_op
+ 
+ bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) const throw()
+ {
+     const bool t = (limit != 0) && (x < limit);
+     if (!t) failure(out_of_range_data);
+     return t;
+ }
+ 
++inline
++bool Machine::Code::decoder::test_ref(int8 index) const throw()
++{
++    if (_code._constraint && !_in_ctxt_item)
++    {
++        if (index > 0 || -index > _max.pre_context)
++        {
++            failure(out_of_range_data);
++            return false;
++        }
++    }
++    else
++        return valid_upto(_max.rule_length, _slotref + _max.pre_context + index);
++    return true;
++}
++
+ bool Machine::Code::decoder::test_context() const throw()
+ {
+-    if (_pre_context >= _rule_length || _analysis.slotref >= analysis::NUMCONTEXTS - 1)
++    if (_out_index >= _out_length || _out_index < 0 || _slotref >= NUMCONTEXTS - 1)
+     {
+         failure(out_of_range_data);
+         return false;
+     }
+     return true;
+ }
+ 
+ inline 
+ void Machine::Code::failure(const status_t s) throw() {
+     release_buffers();
+     _status = s;
+ }
+ 
+ 
+ inline
+-void Machine::Code::decoder::analysis::set_ref(int index, bool incinsert) throw() {
+-    if (incinsert && contexts[slotref].flags.inserted) --index;
+-    if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
+-    contexts[index + slotref].flags.referenced = true;
+-    if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
++void Machine::Code::decoder::set_ref(int index) throw() {
++    if (index + _slotref < 0 || index + _slotref >= NUMCONTEXTS) return;
++    _contexts[index + _slotref].flags.referenced = true;
++    if (index + _slotref > _max_ref) _max_ref = index + _slotref;
+ }
+ 
+ 
+ inline
+-void Machine::Code::decoder::analysis::set_noref(int index) throw() {
+-    if (contexts[slotref].flags.inserted) --index;
+-    if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
+-    if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
++void Machine::Code::decoder::set_noref(int index) throw() {
++    if (index + _slotref < 0 || index + _slotref >= NUMCONTEXTS) return;
++    if (index + _slotref > _max_ref) _max_ref = index + _slotref;
+ }
+ 
+ 
+ inline
+-void Machine::Code::decoder::analysis::set_changed(int index) throw() {
+-    if (contexts[slotref].flags.inserted) --index;
+-    if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
+-    contexts[index + slotref].flags.changed = true;
+-    if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
++void Machine::Code::decoder::set_changed(int index) throw() {
++    if (index + _slotref < 0 || index + _slotref >= NUMCONTEXTS) return;
++    _contexts[index + _slotref].flags.changed= true;
++    if (index + _slotref > _max_ref) _max_ref = index + _slotref;
+ }
+ 
+ 
+ void Machine::Code::release_buffers() throw()
+ {
+     if (_own)
+         free(_code);
+     _code = 0;
+diff --git a/gfx/graphite2/src/Collider.cpp b/gfx/graphite2/src/Collider.cpp
+--- a/gfx/graphite2/src/Collider.cpp
++++ b/gfx/graphite2/src/Collider.cpp
+@@ -21,17 +21,17 @@
+ 
+ Alternatively, the contents of this file may be used under the terms of the
+ Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
+ License, as published by the Free Software Foundation, either version 2
+ of the License or (at your option) any later version.
+ */
+ #include <algorithm>
+ #include <limits>
+-#include <math.h>
++#include <cmath>
+ #include <string>
+ #include <functional>
+ #include "inc/Collider.h"
+ #include "inc/Segment.h"
+ #include "inc/Slot.h"
+ #include "inc/GlyphCache.h"
+ #include "inc/Sparse.h"
+ 
+@@ -824,43 +824,43 @@ bool KernCollider::initSlot(Segment *seg
+     if (margin < 10) margin = 10;
+ 
+     _limit = limit;
+     _offsetPrev = offsetPrev; // kern from a previous pass
+     
+     // Calculate the height of the glyph and how many horizontal slices to use.
+     if (_maxy >= 1e37f)
+     {
+-        _maxy = ymax;
+-        _miny = ymin;
+         _sliceWidth = margin / 1.5f;
++        _maxy = ymax + margin;
++        _miny = ymin - margin;
+         numSlices = int((_maxy - _miny + 2) / (_sliceWidth / 1.5f) + 1.f);  // +2 helps with rounding errors
+         _edges.clear();
+         _edges.insert(_edges.begin(), numSlices, (dir & 1) ? 1e38f : -1e38f);
+         _xbound = (dir & 1) ? (float)1e38f : (float)-1e38f;
+     }
+     else if (_maxy != ymax || _miny != ymin)
+     {
+         if (_miny != ymin)
+         {
+-            numSlices = int((ymin - _miny) / _sliceWidth - 1);
++            numSlices = int((ymin - margin - _miny) / _sliceWidth - 1);
+             _miny += numSlices * _sliceWidth;
+             if (numSlices < 0)
+                 _edges.insert(_edges.begin(), -numSlices, (dir & 1) ? 1e38f : -1e38f);
+             else if ((unsigned)numSlices < _edges.size())    // this shouldn't fire since we always grow the range
+             {
+                 Vector<float>::iterator e = _edges.begin();
+                 while (numSlices--)
+                     ++e;
+                 _edges.erase(_edges.begin(), e);
+             }
+         }
+         if (_maxy != ymax)
+         {
+-            numSlices = int((ymax - _miny) / _sliceWidth + 1);
++            numSlices = int((ymax + margin - _miny) / _sliceWidth + 1);
+             _maxy = numSlices * _sliceWidth + _miny;
+             if (numSlices > (int)_edges.size())
+                 _edges.insert(_edges.end(), numSlices - _edges.size(), (dir & 1) ? 1e38f : -1e38f);
+             else if (numSlices < (int)_edges.size())   // this shouldn't fire since we always grow the range
+             {
+                 while ((int)_edges.size() > numSlices)
+                     _edges.pop_back();
+             }
+@@ -930,53 +930,60 @@ bool KernCollider::initSlot(Segment *seg
+ // Return false if we know there is no collision, true if we think there might be one.
+ bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, GR_MAYBE_UNUSED json * const dbgout)
+ {
+     int rtl = (dir & 1) * 2 - 1;
+     if (!seg->getFace()->glyphs().check(slot->gid()))
+         return false;
+     const Rect &bb = seg->theGlyphBBoxTemporary(slot->gid());
+     const float sx = slot->origin().x + currShift.x;
+-    float x = sx + (rtl > 0 ? bb.tr.x : bb.bl.x);
++    float x = (sx + (rtl > 0 ? bb.tr.x : bb.bl.x)) * rtl;
+     // this isn't going to reduce _mingap so skip
+-    if ((rtl > 0 && x < _xbound - _mingap - currSpace) || (rtl <= 0 && x > _xbound + _mingap + currSpace))
++    if (x < rtl * (_xbound - _mingap - currSpace))
+         return false;
+ 
+     const float sy = slot->origin().y + currShift.y;
+-    int smin = max(0, int((bb.bl.y + (1 - _miny + sy)) / _sliceWidth + 1));
+-    int smax = min((int)_edges.size() - 1, int((bb.tr.y + (1 - _miny + sy)) / _sliceWidth + 1));
++    int smin = max(1, int((bb.bl.y + (1 - _miny + sy)) / _sliceWidth + 1)) - 1;
++    int smax = min((int)_edges.size() - 2, int((bb.tr.y + (1 - _miny + sy)) / _sliceWidth + 1)) + 1;
++    if (smin > smax)
++        return false;
+     bool collides = false;
++    float below = smin > 0 ? _edges[smin-1] * rtl : 1e38f;
++    float here = _edges[smin] * rtl;
++    float above = smin < (int)_edges.size() - 1 ? _edges[smin+1] * rtl : 1e38f;
+ 
+     for (int i = smin; i <= smax; ++i)
+     {
+         float t;
+         float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth);  // vertical center of slice
+-        if (x * rtl > _edges[i] * rtl - _mingap - currSpace)
++        if (    (x > here - _mingap - currSpace)
++             || (x > below - _mingap - currSpace)
++             || (x > above - _mingap - currSpace))
+         {
+             // 2 * currSpace to account for the space that is already separating them and the space we want to add
+-            float m = get_edge(seg, slot, currShift, y, _sliceWidth, rtl > 0) + 2 * rtl * currSpace;
+-            t = rtl * (_edges[i] - m);
++            float m = get_edge(seg, slot, currShift, y, _sliceWidth, rtl > 0) * rtl + 2 * currSpace;
+             // Check slices above and below (if any).
+-            if (i < (int)_edges.size() - 1) t = min(t, rtl * (_edges[i+1] - m));
+-            if (i > 0) t = min(t, rtl * (_edges[i-1] - m));
++            t = min(min(here, below), above) - m;
+             // _mingap is positive to shrink
+             if (t < _mingap)
+             {
+                 _mingap = t;
+                 collides = true;
+             }
+ #if !defined GRAPHITE2_NTRACING
+             // Debugging - remember the closest neighboring edge for this slice.
+-            if (rtl * m > rtl * _nearEdges[i])
++            if (m > rtl * _nearEdges[i])
+             {
+                 _slotNear[i] = slot;
+-                _nearEdges[i] = m;
++                _nearEdges[i] = m * rtl;
+             }
+ #endif
+         }
++        below = here; here = above;
++        above = i < (int)_edges.size() - 2 ? _edges[i+2] * rtl : 1e38f;
+     }
+     return collides;   // note that true is not a necessarily reliable value
+     
+ }   // end of KernCollider::mergeSlot
+ 
+ 
+ // Return the amount to kern by.
+ Position KernCollider::resolve(GR_MAYBE_UNUSED Segment *seg, GR_MAYBE_UNUSED Slot *slot,
+diff --git a/gfx/graphite2/src/Face.cpp b/gfx/graphite2/src/Face.cpp
+--- a/gfx/graphite2/src/Face.cpp
++++ b/gfx/graphite2/src/Face.cpp
+@@ -178,17 +178,18 @@ bool Face::runGraphite(Segment *seg, con
+     if ((seg->dir() & 3) == 3 && aSilf->bidiPass() == 0xFF)
+         seg->doMirror(aSilf->aMirror());
+     bool res = aSilf->runGraphite(seg, 0, aSilf->positionPass(), true);
+     if (res)
+     {
+         seg->associateChars(0, seg->charInfoCount());
+         if (aSilf->flags() & 0x20)
+             res &= seg->initCollisions();
+-        res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
++        if (res)
++            res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
+     }
+ 
+ #if !defined GRAPHITE2_NTRACING
+     if (dbgout)
+ {
+         seg->positionSlots(0, 0, 0, aSilf->dir());
+         *dbgout             << json::item
+                             << json::close // Close up the passes array
+@@ -226,17 +227,17 @@ const Silf *Face::chooseSilf(uint32 scri
+         return m_silfs;
+ }
+ 
+ uint16 Face::findPseudo(uint32 uid) const
+ {
+     return (m_numSilf) ? m_silfs[0].findPseudo(uid) : 0;
+ }
+ 
+-uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const
++int32 Face::getGlyphMetric(uint16 gid, uint8 metric) const
+ {
+     switch (metrics(metric))
+     {
+         case kgmetAscent : return m_ascent;
+         case kgmetDescent : return m_descent;
+         default: 
+             if (gid >= glyphs().numGlyphs()) return 0;
+             return glyphs().glyph(gid)->getMetric(metric);
+@@ -277,17 +278,17 @@ Face::Table::Table(const Face & face, co
+ : _f(&face), _compressed(false)
+ {
+     size_t sz = 0;
+     _p = static_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &sz));
+     _sz = uint32(sz);
+ 
+     if (!TtfUtil::CheckTable(n, _p, _sz))
+     {
+-        this->~Table();     // Make sure we release the table buffer even if the table filed it's checks
++        releaseBuffers();     // Make sure we release the table buffer even if the table failed it's checks
+         return;
+     }
+ 
+     if (be::peek<uint32>(_p) >= version)
+         decompress();
+ }
+ 
+ void Face::Table::releaseBuffers()
+@@ -324,17 +325,18 @@ Error Face::Table::decompress()
+     switch(compression(hdr >> 27))
+     {
+     case NONE: return e;
+ 
+     case LZ4:
+     {
+         uncompressed_size  = hdr & 0x07ffffff;
+         uncompressed_table = gralloc<byte>(uncompressed_size);
+-        if (!e.test(!uncompressed_table, E_OUTOFMEM))
++        if (!e.test(!uncompressed_table || uncompressed_size < 4, E_OUTOFMEM))
++            memset(uncompressed_table, 0, 4);   // make sure version number is initialised
+             // coverity[forward_null : FALSE] - uncompressed_table has been checked so can't be null
+             // coverity[checked_return : FALSE] - we test e later
+             e.test(lz4::decompress(p, _sz - 2*sizeof(uint32), uncompressed_table, uncompressed_size) != signed(uncompressed_size), E_SHRINKERFAILED);
+         break;
+     }
+ 
+     default:
+         e.error(E_BADSCHEME);
+diff --git a/gfx/graphite2/src/GlyphCache.cpp b/gfx/graphite2/src/GlyphCache.cpp
+--- a/gfx/graphite2/src/GlyphCache.cpp
++++ b/gfx/graphite2/src/GlyphCache.cpp
+@@ -111,18 +111,20 @@ private:
+                     _num_glyphs_attributes,
+                     _num_attrs;                    // number of glyph attributes per glyph
+ };
+ 
+ 
+ 
+ GlyphCache::GlyphCache(const Face & face, const uint32 face_options)
+ : _glyph_loader(new Loader(face, bool(face_options & gr_face_dumbRendering))),
+-  _glyphs(_glyph_loader && *_glyph_loader ? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0),
+-  _boxes(_glyph_loader && _glyph_loader->has_boxes() ? grzeroalloc<GlyphBox *>(_glyph_loader->num_glyphs()) : 0),
++  _glyphs(_glyph_loader && *_glyph_loader && _glyph_loader->num_glyphs()
++        ? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0),
++  _boxes(_glyph_loader && _glyph_loader->has_boxes() && _glyph_loader->num_glyphs()
++        ? grzeroalloc<GlyphBox *>(_glyph_loader->num_glyphs()) : 0),
+   _num_glyphs(_glyphs ? _glyph_loader->num_glyphs() : 0),
+   _num_attrs(_glyphs ? _glyph_loader->num_attrs() : 0),
+   _upem(_glyphs ? _glyph_loader->units_per_em() : 0)
+ {
+     if ((face_options & gr_face_preloadGlyphs) && _glyph_loader && _glyphs)
+     {
+         int numsubs = 0;
+         GlyphFace * const glyphs = new GlyphFace [_num_glyphs];
+@@ -139,17 +141,17 @@ GlyphCache::GlyphCache(const Face & face
+         for (uint16 gid = 1; loaded && gid != _num_glyphs; ++gid)
+             _glyphs[gid] = loaded = _glyph_loader->read_glyph(gid, glyphs[gid], &numsubs);
+ 
+         if (!loaded)
+         {
+             _glyphs[0] = 0;
+             delete [] glyphs;
+         }
+-        else if (numsubs > 0)
++        else if (numsubs > 0 && _boxes)
+         {
+             GlyphBox * boxes = (GlyphBox *)gralloc<char>(_num_glyphs * sizeof(GlyphBox) + numsubs * 8 * sizeof(float));
+             GlyphBox * currbox = boxes;
+ 
+             for (uint16 gid = 0; currbox && gid != _num_glyphs; ++gid)
+             {
+                 _boxes[gid] = currbox;
+                 currbox = _glyph_loader->read_box(gid, currbox, *_glyphs[gid]);
+@@ -204,16 +206,18 @@ GlyphCache::~GlyphCache()
+             free(_boxes[0]);
+         free(_boxes);
+     }
+     delete _glyph_loader;
+ }
+ 
+ const GlyphFace *GlyphCache::glyph(unsigned short glyphid) const      //result may be changed by subsequent call with a different glyphid
+ { 
++    if (glyphid >= numGlyphs())
++        return _glyphs[0];
+     const GlyphFace * & p = _glyphs[glyphid];
+     if (p == 0 && _glyph_loader)
+     {
+         int numsubs = 0;
+         GlyphFace * g = new GlyphFace();
+         if (g)  p = _glyph_loader->read_glyph(glyphid, *g, &numsubs);
+         if (!p)
+         {
+@@ -280,26 +284,27 @@ GlyphCache::Loader::Loader(const Face & 
+         _long_fmt              = flags & 1;
+         int tmpnumgattrs       = (m_pGloc.size()
+                                    - (p - m_pGloc)
+                                    - sizeof(uint16)*(flags & 0x2 ? _num_attrs : 0))
+                                        / (_long_fmt ? sizeof(uint32) : sizeof(uint16)) - 1;
+ 
+         if (version >= 0x00020000 || tmpnumgattrs < 0 || tmpnumgattrs > 65535
+             || _num_attrs == 0 || _num_attrs > 0x3000  // is this hard limit appropriate?
+-            || _num_glyphs_graphics > tmpnumgattrs)
++            || _num_glyphs_graphics > tmpnumgattrs
++            || m_pGlat.size() < 4)
+         {
+             _head = Face::Table();
+             return;
+         }
+ 
+         _num_glyphs_attributes = static_cast<unsigned short>(tmpnumgattrs);
+         p = m_pGlat;
+         version = be::read<uint32>(p);
+-        if (version >= 0x00040000)       // reject Glat tables that are too new
++        if (version >= 0x00040000 || (version >= 0x00030000 && m_pGlat.size() < 8))       // reject Glat tables that are too new
+         {
+             _head = Face::Table();
+             return;
+         }
+         else if (version >= 0x00030000)
+         {
+             unsigned int glatflags = be::read<uint32>(p);
+             _has_boxes = glatflags & 1;
+@@ -381,22 +386,24 @@ const GlyphFace * GlyphCache::Loader::re
+         }
+         else
+         {
+             be::skip<uint16>(gloc, glyphid);
+             glocs = be::read<uint16>(gloc);
+             gloce = be::peek<uint16>(gloc);
+         }
+ 
+-        if (glocs >= m_pGlat.size() || gloce > m_pGlat.size())
++        if (glocs >= m_pGlat.size() - 1 || gloce > m_pGlat.size())
+             return 0;
+ 
+         const uint32 glat_version = be::peek<uint32>(m_pGlat);
+-        if (glat_version == 0x00030000)
++        if (glat_version >= 0x00030000)
+         {
++            if (glocs >= gloce)
++                return 0;
+             const byte * p = m_pGlat + glocs;
+             uint16 bmap = be::read<uint16>(p);
+             int num = bit_set_count((uint32)bmap);
+             if (numsubs) *numsubs += num;
+             glocs += 6 + 8 * num;
+             if (glocs > gloce)
+                 return 0;
+         }
+@@ -449,29 +456,31 @@ GlyphBox * GlyphCache::Loader::read_box(
+     }
+     else
+     {
+         be::skip<uint16>(gloc, gid);
+         glocs = be::read<uint16>(gloc);
+         gloce = be::peek<uint16>(gloc);
+     }
+ 
+-    if (glocs >= m_pGlat.size() || gloce > m_pGlat.size())
++    if (gloce > m_pGlat.size() || glocs + 6 >= gloce)
+         return 0;
+ 
+     const byte * p = m_pGlat + glocs;
+     uint16 bmap = be::read<uint16>(p);
+     int num = bit_set_count((uint32)bmap);
+ 
+     Rect bbox = glyph.theBBox();
+     Rect diamax(Position(bbox.bl.x + bbox.bl.y, bbox.bl.x - bbox.tr.y),
+                 Position(bbox.tr.x + bbox.tr.y, bbox.tr.x - bbox.bl.y));
+     Rect diabound = readbox(diamax, p[0], p[2], p[1], p[3]);
+     ::new (curr) GlyphBox(num, bmap, &diabound);
+     be::skip<uint8>(p, 4);
++    if (glocs + 6 + num * 8 >= gloce)
++        return 0;
+ 
+     for (int i = 0; i < num * 2; ++i)
+     {
+         Rect box = readbox((i & 1) ? diamax : bbox, p[0], p[2], p[1], p[3]);
+         curr->addSubBox(i >> 1, i & 1, &box);
+         be::skip<uint8>(p, 4);
+     } 
+     return (GlyphBox *)((char *)(curr) + sizeof(GlyphBox) + 2 * num * sizeof(Rect));
+diff --git a/gfx/graphite2/src/GlyphFace.cpp b/gfx/graphite2/src/GlyphFace.cpp
+--- a/gfx/graphite2/src/GlyphFace.cpp
++++ b/gfx/graphite2/src/GlyphFace.cpp
+@@ -24,25 +24,25 @@ Mozilla Public License (http://mozilla.o
+ License, as published by the Free Software Foundation, either version 2
+ of the License or (at your option) any later version.
+ */
+ #include "inc/GlyphFace.h"
+ 
+ 
+ using namespace graphite2;
+ 
+-uint16 GlyphFace::getMetric(uint8 metric) const
++int32 GlyphFace::getMetric(uint8 metric) const
+ {
+     switch (metrics(metric))
+     {
+-        case kgmetLsb       : return static_cast<uint16>(m_bbox.bl.x);
+-        case kgmetRsb       : return static_cast<uint16>(m_advance.x - m_bbox.tr.x);
+-        case kgmetBbTop     : return static_cast<uint16>(m_bbox.tr.y);
+-        case kgmetBbBottom  : return static_cast<uint16>(m_bbox.bl.y);
+-        case kgmetBbLeft    : return static_cast<uint16>(m_bbox.bl.x);
+-        case kgmetBbRight   : return static_cast<uint16>(m_bbox.tr.x);
+-        case kgmetBbHeight  : return static_cast<uint16>(m_bbox.tr.y - m_bbox.bl.y);
+-        case kgmetBbWidth   : return static_cast<uint16>(m_bbox.tr.x - m_bbox.bl.x);
+-        case kgmetAdvWidth  : return static_cast<uint16>(m_advance.x);
+-        case kgmetAdvHeight : return static_cast<uint16>(m_advance.y);
++        case kgmetLsb       : return m_bbox.bl.x;
++        case kgmetRsb       : return m_advance.x - m_bbox.tr.x;
++        case kgmetBbTop     : return m_bbox.tr.y;
++        case kgmetBbBottom  : return m_bbox.bl.y;
++        case kgmetBbLeft    : return m_bbox.bl.x;
++        case kgmetBbRight   : return m_bbox.tr.x;
++        case kgmetBbHeight  : return m_bbox.tr.y - m_bbox.bl.y;
++        case kgmetBbWidth   : return m_bbox.tr.x - m_bbox.bl.x;
++        case kgmetAdvWidth  : return m_advance.x;
++        case kgmetAdvHeight : return m_advance.y;
+         default : return 0;
+     }
+ }
+diff --git a/gfx/graphite2/src/Justifier.cpp b/gfx/graphite2/src/Justifier.cpp
+--- a/gfx/graphite2/src/Justifier.cpp
++++ b/gfx/graphite2/src/Justifier.cpp
+@@ -95,62 +95,63 @@ float Segment::justify(Slot *pSlot, cons
+ 
+     end = pLast->nextSibling();
+     pFirst = pFirst->nextSibling();
+ 
+     int icount = 0;
+     int numLevels = silf()->numJustLevels();
+     if (!numLevels)
+     {
+-        for (s = pSlot; s != end; s = s->next())
++        for (s = pSlot; s && s != end; s = s->nextSibling())
+         {
+             CharInfo *c = charinfo(s->before());
+             if (isWhitespace(c->unicodeChar()))
+             {
+                 s->setJustify(this, 0, 3, 1);
+                 s->setJustify(this, 0, 2, 1);
+                 s->setJustify(this, 0, 0, -1);
+                 ++icount;
+             }
+         }
+         if (!icount)
+         {
+-            for (s = pSlot; s != end; s = s->nextSibling())
++            for (s = pSlot; s && s != end; s = s->nextSibling())
+             {
+                 s->setJustify(this, 0, 3, 1);
+                 s->setJustify(this, 0, 2, 1);
+                 s->setJustify(this, 0, 0, -1);
+             }
+         }
+         ++numLevels;
+     }
+ 
+     Vector<JustifyTotal> stats(numLevels);
+-    for (s = pFirst; s != end; s = s->nextSibling())
++    for (s = pFirst; s && s != end; s = s->nextSibling())
+     {
+         float w = s->origin().x / scale + s->advance() - base;
+         if (w > currWidth) currWidth = w;
+         for (int j = 0; j < numLevels; ++j)
+             stats[j].accumulate(s, this, j);
+         s->just(0);
+     }
+ 
+     for (int i = (width < 0.0f) ? -1 : numLevels - 1; i >= 0; --i)
+     {
+         float diff;
+         float error = 0.;
+         float diffpw;
+         int tWeight = stats[i].weight();
++        if (tWeight == 0) continue;
+ 
+         do {
+             error = 0.;
+             diff = width - currWidth;
+             diffpw = diff / tWeight;
+             tWeight = 0;
+-            for (s = pFirst; s != end; s = s->nextSibling()) // don't include final glyph
++            for (s = pFirst; s && s != end; s = s->nextSibling()) // don't include final glyph
+             {
+                 int w = s->getJustify(this, i, 3);
+                 float pref = diffpw * w + error;
+                 int step = s->getJustify(this, i, 2);
+                 if (!step) step = 1;        // handle lazy font developers
+                 if (pref > 0)
+                 {
+                     float max = uint16(s->getJustify(this, i, 0));
+diff --git a/gfx/graphite2/src/NameTable.cpp b/gfx/graphite2/src/NameTable.cpp
+--- a/gfx/graphite2/src/NameTable.cpp
++++ b/gfx/graphite2/src/NameTable.cpp
+@@ -42,25 +42,26 @@ NameTable::NameTable(const void* data, s
+     memcpy(pdata, data, length);
+     m_table = reinterpret_cast<const TtfUtil::Sfnt::FontNames*>(pdata);
+ 
+     if ((length > sizeof(TtfUtil::Sfnt::FontNames)) &&
+         (length > sizeof(TtfUtil::Sfnt::FontNames) +
+          sizeof(TtfUtil::Sfnt::NameRecord) * ( be::swap<uint16>(m_table->count) - 1)))
+     {
+         uint16 offset = be::swap<uint16>(m_table->string_offset);
+-        m_nameData = reinterpret_cast<const uint8*>(pdata) + offset;
+-        setPlatformEncoding(platformId, encodingID);
+-        m_nameDataLength = length - offset;
++        if (offset < length)
++        {
++            m_nameData = reinterpret_cast<const uint8*>(pdata) + offset;
++            setPlatformEncoding(platformId, encodingID);
++            m_nameDataLength = length - offset;
++            return;
++        }
+     }
+-    else
+-    {
+-        free(const_cast<TtfUtil::Sfnt::FontNames*>(m_table));
+-        m_table = NULL;
+-    }
++    free(const_cast<TtfUtil::Sfnt::FontNames*>(m_table));
++    m_table = NULL;
+ }
+ 
+ uint16 NameTable::setPlatformEncoding(uint16 platformId, uint16 encodingID)
+ {
+     if (!m_nameData) return 0;
+     uint16 i = 0;
+     uint16 count = be::swap<uint16>(m_table->count);
+     for (; i < count; i++)
+@@ -139,28 +140,36 @@ void* NameTable::getName(uint16& languag
+     uint16 offset = be::swap<uint16>(nameRecord.offset);
+     if(offset + utf16Length > m_nameDataLength)
+     {
+         languageId = 0;
+         length = 0;
+         return NULL;
+     }
+     utf16Length >>= 1; // in utf16 units
+-    utf16::codeunit_t * utf16Name = gralloc<utf16::codeunit_t>(utf16Length);
++    utf16::codeunit_t * utf16Name = gralloc<utf16::codeunit_t>(utf16Length + 1);
+     if (!utf16Name)
+     {
+         languageId = 0;
+         length = 0;
+         return NULL;
+     }
+     const uint8* pName = m_nameData + offset;
+     for (size_t i = 0; i < utf16Length; i++)
+     {
+         utf16Name[i] = be::read<uint16>(pName);
+     }
++    utf16Name[utf16Length] = 0;
++    if (!utf16::validate(utf16Name, utf16Name + utf16Length))
++    {
++        free(utf16Name);
++        languageId = 0;
++        length = 0;
++        return NULL;
++    }
+     switch (enc)
+     {
+     case gr_utf8:
+     {
+         utf8::codeunit_t* uniBuffer = gralloc<utf8::codeunit_t>(3 * utf16Length + 1);
+         if (!uniBuffer)
+         {
+             free(utf16Name);
+diff --git a/gfx/graphite2/src/Pass.cpp b/gfx/graphite2/src/Pass.cpp
+--- a/gfx/graphite2/src/Pass.cpp
++++ b/gfx/graphite2/src/Pass.cpp
+@@ -96,17 +96,17 @@ bool Pass::readPass(const byte * const p
+     const byte * p              = pass_start,
+                * const pass_end = p + pass_length;
+     size_t numRanges;
+ 
+     if (e.test(pass_length < 40, E_BADPASSLENGTH)) return face.error(e); 
+     // Read in basic values
+     const byte flags = be::read<byte>(p);
+     if (e.test((flags & 0x1f) && 
+-            (pt < PASS_TYPE_POSITIONING || !m_silf->aCollision() || !face.glyphs().hasBoxes()),
++            (pt < PASS_TYPE_POSITIONING || !m_silf->aCollision() || !face.glyphs().hasBoxes() || !(m_silf->flags() & 0x20)),
+             E_BADCOLLISIONPASS))
+         return face.error(e);
+     m_numCollRuns = flags & 0x7;
+     m_kernColls   = (flags >> 3) & 0x3;
+     m_isReverseDir = (flags >> 5) & 0x1;
+     m_iMaxLoop = be::read<byte>(p);
+     if (m_iMaxLoop < 1) m_iMaxLoop = 1;
+     be::skip<byte>(p,2); // skip maxContext & maxBackup
+@@ -226,17 +226,21 @@ bool Pass::readRules(const byte * rule_m
+     // Load rules.
+     const byte * ac_begin = 0, * rc_begin = 0,
+                * ac_end = ac_data + be::peek<uint16>(o_action),
+                * rc_end = rc_data + be::peek<uint16>(o_constraint);
+ 
+     // Allocate pools
+     m_rules = new Rule [m_numRules];
+     m_codes = new Code [m_numRules*2];
+-    const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data);
++    int totalSlots = 0;
++    const uint16 *tsort = sort_key;
++    for (int i = 0; i < m_numRules; ++i)
++        totalSlots += be::peek<uint16>(--tsort);
++    const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data, 2 * m_numRules, totalSlots);
+     m_progs = gralloc<byte>(prog_pool_sz);
+     byte * prog_pool_free = m_progs,
+          * prog_pool_end  = m_progs + prog_pool_sz;
+     if (e.test(!(m_rules && m_codes && m_progs), E_OUTOFMEM)) return face.error(e);
+ 
+     Rule * r = m_rules + m_numRules - 1;
+     for (size_t n = m_numRules; r >= m_rules; --n, --r, ac_end = ac_begin, rc_end = rc_begin)
+     {
+@@ -249,17 +253,17 @@ bool Pass::readRules(const byte * rule_m
+         if (r->sort > 63 || r->preContext >= r->sort || r->preContext > m_maxPreCtxt || r->preContext < m_minPreCtxt)
+             return false;
+         ac_begin      = ac_data + be::peek<uint16>(--o_action);
+         --o_constraint;
+         rc_begin      = be::peek<uint16>(o_constraint) ? rc_data + be::peek<uint16>(o_constraint) : rc_end;
+ 
+         if (ac_begin > ac_end || ac_begin > ac_data_end || ac_end > ac_data_end
+                 || rc_begin > rc_end || rc_begin > rc_data_end || rc_end > rc_data_end
+-                || vm::Machine::Code::estimateCodeDataOut(ac_end - ac_begin + rc_end - rc_begin) > size_t(prog_pool_end - prog_pool_free))
++                || vm::Machine::Code::estimateCodeDataOut(ac_end - ac_begin + rc_end - rc_begin, 2, r->sort) > size_t(prog_pool_end - prog_pool_free))
+             return false;
+         r->action     = new (m_codes+n*2-2) vm::Machine::Code(false, ac_begin, ac_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free);
+         r->constraint = new (m_codes+n*2-1) vm::Machine::Code(true,  rc_begin, rc_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free);
+ 
+         if (e.test(!r->action || !r->constraint, E_OUTOFMEM)
+                 || e.test(r->action->status() != Code::loaded, r->action->status() + E_CODEFAILURE)
+                 || e.test(r->constraint->status() != Code::loaded, r->constraint->status() + E_CODEFAILURE)
+                 || e.test(!r->constraint->immutable(), E_MUTABLECCODE))
+@@ -330,17 +334,17 @@ bool Pass::readStates(const byte * start
+ 
+     // load state transition table.
+     for (uint16 * t = m_transitions,
+                 * const t_end = t + m_numTransition*m_numColumns; t != t_end; ++t)
+     {
+         *t = be::read<uint16>(states);
+         if (e.test(*t >= m_numStates, E_BADSTATE))
+         {
+-            face.error_context((face.error_context() & 0xFFFF00) + EC_ATRANS + (((t - m_transitions) / m_numColumns) << 24));
++            face.error_context((face.error_context() & 0xFFFF00) + EC_ATRANS + (((t - m_transitions) / m_numColumns) << 8));
+             return face.error(e);
+         }
+     }
+ 
+     State * s = m_states,
+           * const success_begin = m_states + m_numStates - m_numSuccess;
+     const RuleEntry * rule_map_end = m_ruleMap + be::peek<uint16>(o_rule_map + m_numSuccess*sizeof(uint16));
+     for (size_t n = m_numStates; n; --n, ++s)
+@@ -351,17 +355,18 @@ bool Pass::readStates(const byte * start
+         if (e.test(begin >= rule_map_end || end > rule_map_end || begin > end, E_BADRULEMAPPING))
+         {
+             face.error_context((face.error_context() & 0xFFFF00) + EC_ARULEMAP + (n << 24));
+             return face.error(e);
+         }
+         s->rules = begin;
+         s->rules_end = (end - begin <= FiniteStateMachine::MAX_RULES)? end :
+             begin + FiniteStateMachine::MAX_RULES;
+-        qsort(begin, end - begin, sizeof(RuleEntry), &cmpRuleEntry);
++        if (begin)      // keep UBSan happy can't call qsort with null begin
++            qsort(begin, end - begin, sizeof(RuleEntry), &cmpRuleEntry);
+     }
+ 
+     return true;
+ }
+ 
+ bool Pass::readRanges(const byte * ranges, size_t num_ranges, Error &e)
+ {
+     m_cols = gralloc<uint16>(m_numGlyphs);
+@@ -449,19 +454,19 @@ bool Pass::runFSM(FiniteStateMachine& fs
+     if (fsm.slots.context() < m_minPreCtxt)
+         return false;
+ 
+     uint16 state = m_startStates[m_maxPreCtxt - fsm.slots.context()];
+     uint8  free_slots = SlotMap::MAX_SLOTS;
+     do
+     {
+         fsm.slots.pushSlot(slot);
+-        if (--free_slots == 0
+-         || slot->gid() >= m_numGlyphs
++        if (slot->gid() >= m_numGlyphs
+          || m_cols[slot->gid()] == 0xffffU
++         || --free_slots == 0
+          || state >= m_numTransition)
+             return free_slots != 0;
+ 
+         const uint16 * transitions = m_transitions + state*m_numColumns;
+         state = transitions[m_cols[slot->gid()]];
+         if (state >= m_successStart)
+             fsm.rules.accumulate_rules(m_states[state]);
+ 
+@@ -627,37 +632,40 @@ bool Pass::testPassConstraint(Machine & 
+ }
+ 
+ 
+ bool Pass::testConstraint(const Rule & r, Machine & m) const
+ {
+     const uint16 curr_context = m.slotMap().context();
+     if (unsigned(r.sort - r.preContext) > m.slotMap().size() - curr_context
+         || curr_context - r.preContext < 0) return false;
++
++    vm::slotref * map = m.slotMap().begin() + curr_context - r.preContext;
++    if (map[r.sort - 1] == 0)
++        return false;
++
+     if (!*r.constraint) return true;
+     assert(r.constraint->constraint());
+-
+-    vm::slotref * map = m.slotMap().begin() + curr_context - r.preContext;
+     for (int n = r.sort; n && map; --n, ++map)
+     {
+         if (!*map) continue;
+         const int32 ret = r.constraint->run(m, map);
+         if (!ret || m.status() != Machine::finished)
+             return false;
+     }
+ 
+     return true;
+ }
+ 
+ 
+ void SlotMap::collectGarbage(Slot * &aSlot)
+ {
+     for(Slot **s = begin(), *const *const se = end() - 1; s != se; ++s) {
+         Slot *& slot = *s;
+-        if(slot->isDeleted() || slot->isCopied())
++        if(slot && (slot->isDeleted() || slot->isCopied()))
+         {
+             if (slot == aSlot)
+                 aSlot = slot->prev() ? slot->prev() : slot->next();
+             segment.freeSlot(slot);
+         }
+     }
+ }
+ 
+@@ -848,17 +856,16 @@ bool Pass::collisionShift(Segment *seg, 
+             }
+         }
+     }
+     return true;
+ }
+ 
+ bool Pass::collisionKern(Segment *seg, int dir, json * const dbgout) const
+ {
+-    KernCollider kerncoll(dbgout);
+     Slot *start = seg->first();
+     float ymin = 1e38f;
+     float ymax = -1e38f;
+     const GlyphCache &gc = seg->getFace()->glyphs();
+ 
+     // phase 3 : handle kerning of clusters
+ #if !defined GRAPHITE2_NTRACING
+     if (dbgout)
+@@ -871,17 +878,17 @@ bool Pass::collisionKern(Segment *seg, i
+             return false;
+         const SlotCollision * c = seg->collisionInfo(s);
+         const Rect &bbox = seg->theGlyphBBoxTemporary(s->gid());
+         float y = s->origin().y + c->shift().y;
+         ymax = max(y + bbox.tr.y, ymax);
+         ymin = min(y + bbox.bl.y, ymin);
+         if (start && (c->flags() & (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX))
+                         == (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX))
+-            resolveKern(seg, s, start, kerncoll, dir, ymin, ymax, dbgout);
++            resolveKern(seg, s, start, dir, ymin, ymax, dbgout);
+         if (c->flags() & SlotCollision::COLL_END)
+             start = NULL;
+         if (c->flags() & SlotCollision::COLL_START)
+             start = s;
+     }
+ 
+ #if !defined GRAPHITE2_NTRACING
+     if (dbgout)
+@@ -1010,17 +1017,17 @@ bool Pass::resolveCollisions(Segment *se
+     if (isCol)
+     { cFix->setFlags(cFix->flags() | SlotCollision::COLL_ISCOL | SlotCollision::COLL_KNOWN); }
+     else
+     { cFix->setFlags((cFix->flags() & ~SlotCollision::COLL_ISCOL) | SlotCollision::COLL_KNOWN); }
+     hasCol |= isCol;
+     return true;
+ }
+ 
+-float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start, KernCollider &coll, int dir,
++float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start, int dir,
+     float &ymin, float &ymax, json *const dbgout) const
+ {
+     Slot *nbor; // neighboring slot
+     float currSpace = 0.;
+     bool collides = false;
+     unsigned int space_count = 0;
+     Slot *base = slotFix;
+     while (base->attachedTo())
+@@ -1030,16 +1037,17 @@ float Pass::resolveKern(Segment *seg, Sl
+ 
+     if (base != slotFix)
+     {
+         cFix->setFlags(cFix->flags() | SlotCollision::COLL_KERN | SlotCollision::COLL_FIX);
+         return 0;
+     }
+     bool seenEnd = (cFix->flags() & SlotCollision::COLL_END) != 0;
+     bool isInit = false;
++    KernCollider coll(dbgout);
+ 
+     for (nbor = slotFix->next(); nbor; nbor = nbor->next())
+     {
+         if (nbor->isChildOf(base))
+             continue;
+         if (!gc.check(nbor->gid()))
+             return 0.;
+         const Rect &bb = seg->theGlyphBBoxTemporary(nbor->gid());
+diff --git a/gfx/graphite2/src/Segment.cpp b/gfx/graphite2/src/Segment.cpp
+--- a/gfx/graphite2/src/Segment.cpp
++++ b/gfx/graphite2/src/Segment.cpp
+@@ -419,16 +419,19 @@ Position Segment::positionSlots(const Fo
+         reverseSlots();
+         temp = iStart;
+         iStart = iEnd;
+         iEnd = temp;
+     }
+     if (!iStart)    iStart = m_first;
+     if (!iEnd)      iEnd   = m_last;
+ 
++    if (!iStart || !iEnd)   // only true for empty segments
++        return currpos;
++
+     if (isRtl)
+     {
+         for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
+         {
+             if (s->isBase())
+                 currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
+         }
+     }
+@@ -526,11 +529,14 @@ void Segment::doMirror(uint16 aMirror)
+ }
+ 
+ bool Segment::initCollisions()
+ {
+     m_collisions = grzeroalloc<SlotCollision>(slotCount());
+     if (!m_collisions) return false;
+ 
+     for (Slot *p = m_first; p; p = p->next())
+-        ::new (collisionInfo(p)) SlotCollision(this, p);
++        if (p->index() < slotCount())
++            ::new (collisionInfo(p)) SlotCollision(this, p);
++        else
++            return false;
+     return true;
+ }
+diff --git a/gfx/graphite2/src/Silf.cpp b/gfx/graphite2/src/Silf.cpp
+--- a/gfx/graphite2/src/Silf.cpp
++++ b/gfx/graphite2/src/Silf.cpp
+@@ -350,20 +350,20 @@ uint16 Silf::getClassGlyph(uint16 cid, u
+     }
+     return 0;
+ }
+ 
+ 
+ bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi) const
+ {
+     assert(seg != 0);
+-    SlotMap            map(*seg, m_dir);
++    unsigned int       maxSize = seg->slotCount() * MAX_SEG_GROWTH_FACTOR;
++    SlotMap            map(*seg, m_dir, maxSize);
+     FiniteStateMachine fsm(map, seg->getFace()->logger());
+     vm::Machine        m(map);
+-    unsigned int       initSize = seg->slotCount();
+     uint8              lbidi = m_bPass;
+ #if !defined GRAPHITE2_NTRACING
+     json * const dbgout = seg->getFace()->logger();
+ #endif
+ 
+     if (lastPass == 0)
+     {
+         if (firstPass == lastPass && lbidi == 0xFF)
+@@ -419,13 +419,13 @@ bool Silf::runGraphite(Segment *seg, uin
+ 
+         // test whether to reorder, prepare for positioning
+         bool reverse = (lbidi == 0xFF) && (seg->currdir() != ((m_dir & 1) ^ m_passes[i].reverseDir()));
+         if ((i >= 32 || (seg->passBits() & (1 << i)) == 0 || m_passes[i].collisionLoops())
+                 && !m_passes[i].runGraphite(m, fsm, reverse))
+             return false;
+         // only subsitution passes can change segment length, cached subsegments are short for their text
+         if (m.status() != vm::Machine::finished
+-            || (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize))
++            || (seg->slotCount() && seg->slotCount() > maxSize))
+             return false;
+     }
+     return true;
+ }
+diff --git a/gfx/graphite2/src/Slot.cpp b/gfx/graphite2/src/Slot.cpp
+--- a/gfx/graphite2/src/Slot.cpp
++++ b/gfx/graphite2/src/Slot.cpp
+@@ -80,20 +80,20 @@ void Slot::set(const Slot & orig, int ch
+ 
+ void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos)
+ {
+     m_before += numCharInfo;
+     m_after += numCharInfo;
+     m_position = m_position + relpos;
+ }
+ 
+-Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal)
++Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal, int depth)
+ {
+     SlotCollision *coll = NULL;
+-    if (attrLevel && m_attLevel > attrLevel) return Position(0, 0);
++    if (depth > 100 || (attrLevel && m_attLevel > attrLevel)) return Position(0, 0);
+     float scale = font ? font->scale() : 1.0f;
+     Position shift(m_shift.x * (rtl * -2 + 1) + m_just, m_shift.y);
+     float tAdvance = m_advance.x + m_just;
+     if (isFinal && (coll = seg->collisionInfo(this)))
+     {
+         const Position &collshift = coll->offset();
+         if (!(coll->flags() & SlotCollision::COLL_KERN) || rtl)
+             shift = shift + collshift;
+@@ -128,23 +128,23 @@ Position Slot::finalise(const Segment *s
+     if (glyphFace)
+     {
+         Rect ourBbox = glyphFace->theBBox() * scale + m_position;
+         bbox = bbox.widen(ourBbox);
+     }
+ 
+     if (m_child && m_child != this && m_child->attachedTo() == this)
+     {
+-        Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin, rtl, isFinal);
++        Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin, rtl, isFinal, depth + 1);
+         if ((!m_parent || m_advance.x >= 0.5f) && tRes.x > res.x) res = tRes;
+     }
+ 
+     if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent)
+     {
+-        Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin, rtl, isFinal);
++        Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin, rtl, isFinal, depth + 1);
+         if (tRes.x > res.x) res = tRes;
+     }
+     
+     if (!m_parent && clusterMin < base.x)
+     {
+         Position adj = Position(m_position.x - clusterMin, 0.);
+         res += adj;
+         m_position += adj;
+@@ -160,35 +160,35 @@ int32 Slot::clusterMetric(const Segment 
+         return 0;
+     Rect bbox = seg->theGlyphBBoxTemporary(glyph());
+     float clusterMin = 0.;
+     Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin, rtl, false);
+ 
+     switch (metrics(metric))
+     {
+     case kgmetLsb :
+-        return static_cast<uint32>(bbox.bl.x);
++        return bbox.bl.x;
+     case kgmetRsb :
+-        return static_cast<uint32>(res.x - bbox.tr.x);
++        return res.x - bbox.tr.x;
+     case kgmetBbTop :
+-        return static_cast<uint32>(bbox.tr.y);
++        return bbox.tr.y;
+     case kgmetBbBottom :
+-        return static_cast<uint32>(bbox.bl.y);
++        return bbox.bl.y;
+     case kgmetBbLeft :
+-        return static_cast<uint32>(bbox.bl.x);
++        return bbox.bl.x;
+     case kgmetBbRight :
+-        return static_cast<uint32>(bbox.tr.x);
++        return bbox.tr.x;
+     case kgmetBbWidth :
+-        return static_cast<uint32>(bbox.tr.x - bbox.bl.x);
++        return bbox.tr.x - bbox.bl.x;
+     case kgmetBbHeight :
+-        return static_cast<uint32>(bbox.tr.y - bbox.bl.y);
++        return bbox.tr.y - bbox.bl.y;
+     case kgmetAdvWidth :
+-        return static_cast<uint32>(res.x);
++        return res.x;
+     case kgmetAdvHeight :
+-        return static_cast<uint32>(res.y);
++        return res.y;
+     default :
+         return 0;
+     }
+ }
+ 
+ #define SLOTGETCOLATTR(x) { SlotCollision *c = seg->collisionInfo(this); return c ? int(c-> x) : 0; }
+ 
+ int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
+@@ -290,19 +290,32 @@ void Slot::setAttr(Segment *seg, attrCod
+     case gr_slatAdvX :  m_advance.x = value; break;
+     case gr_slatAdvY :  m_advance.y = value; break;
+     case gr_slatAttTo :
+     {
+         const uint16 idx = uint16(value);
+         if (idx < map.size() && map[idx])
+         {
+             Slot *other = map[idx];
+-            if (other == this || other == m_parent) break;
+-            if (m_parent) m_parent->removeChild(this);
+-            if (!other->isChildOf(this) && other->child(this))
++            if (other == this || other == m_parent || other->isCopied()) break;
++            if (m_parent) { m_parent->removeChild(this); attachTo(NULL); }
++            Slot *pOther = other;
++            int count = 0;
++            bool foundOther = false;
++            while (pOther)
++            {
++                ++count;
++                if (pOther == this) foundOther = true;
++                pOther = pOther->attachedTo();
++            }
++            for (pOther = m_child; pOther; pOther = pOther->m_child)
++                ++count;
++            for (pOther = m_sibling; pOther; pOther = pOther->m_sibling)
++                ++count;
++            if (count < 100 && !foundOther && other->child(this))
+             {
+                 attachTo(other);
+                 if ((map.dir() != 0) ^ (idx > subindex))
+                     m_with = Position(advance(), 0);
+                 else        // normal match to previous root
+                     m_attach = Position(other->advance(), 0);
+             }
+         }
+@@ -416,41 +429,34 @@ bool Slot::sibling(Slot *ap)
+         m_sibling = ap;
+     else
+         return m_sibling->sibling(ap);
+     return true;
+ }
+ 
+ bool Slot::removeChild(Slot *ap)
+ {
+-    if (this == ap || !m_child) return false;
++    if (this == ap || !m_child || !ap) return false;
+     else if (ap == m_child)
+     {
+         Slot *nSibling = m_child->nextSibling();
+-        m_child->removeSibling(nSibling);
++        m_child->nextSibling(NULL);
+         m_child = nSibling;
+         return true;
+     }
+-    else
+-        return m_child->removeSibling(ap);
+-    return true;
+-}
+-
+-bool Slot::removeSibling(Slot *ap)
+-{
+-    if (this == ap || !m_sibling) return false;
+-    else if (ap == m_sibling)
++    for (Slot *p = m_child; p; p = p->m_sibling)
+     {
+-        m_sibling = m_sibling->nextSibling();
+-        if (m_sibling) ap->removeSibling(m_sibling);
+-        return true;
++        if (p->m_sibling && p->m_sibling == ap)
++        {
++            p->m_sibling = p->m_sibling->m_sibling;
++            ap->nextSibling(NULL);
++            return true;
++        }
+     }
+-    else
+-        return m_sibling->removeSibling(ap);
+-    return true;
++    return false;
+ }
+ 
+ void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
+ {
+     m_glyphid = glyphid;
+     m_bidiCls = -1;
+     if (!theGlyph)
+     {
+@@ -475,21 +481,23 @@ void Slot::setGlyph(Segment *seg, uint16
+     if (seg->silf()->aPassBits())
+     {
+         seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]);
+         if (seg->silf()->numPasses() > 16)
+             seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()+1] << 16);
+     }
+ }
+ 
+-void Slot::floodShift(Position adj)
++void Slot::floodShift(Position adj, int depth)
+ {
++    if (depth > 100)
++        return;
+     m_position += adj;
+-    if (m_child) m_child->floodShift(adj);
+-    if (m_sibling) m_sibling->floodShift(adj);
++    if (m_child) m_child->floodShift(adj, depth + 1);
++    if (m_sibling) m_sibling->floodShift(adj, depth + 1);
+ }
+ 
+ void SlotJustify::LoadSlot(const Slot *s, const Segment *seg)
+ {
+     for (int i = seg->silf()->numJustLevels() - 1; i >= 0; --i)
+     {
+         Justinfo *justs = seg->silf()->justAttrs() + i;
+         int16 *v = values + i * NUMJUSTPARAMS;
+@@ -514,15 +522,14 @@ Slot * Slot::nextInCluster(const Slot *s
+             return base->nextSibling();
+         s = base;
+     }
+     return NULL;
+ }
+ 
+ bool Slot::isChildOf(const Slot *base) const
+ {
+-    if (m_parent == base)
+-        return true;
+-    else if (!m_parent)
+-        return false;
+-    else
+-        return m_parent->isChildOf(base);
++    for (Slot *p = m_parent; p; p = p->m_parent)
++        if (p == base)
++            return true;
++    return false;
+ }
++
+diff --git a/gfx/graphite2/src/TtfUtil.cpp b/gfx/graphite2/src/TtfUtil.cpp
+--- a/gfx/graphite2/src/TtfUtil.cpp
++++ b/gfx/graphite2/src/TtfUtil.cpp
+@@ -891,25 +891,27 @@ const void * FindCmapSubtable(const void
+ ----------------------------------------------------------------------------------------------*/
+ bool CheckCmapSubtable4(const void * pCmapSubtable4, const void * pCmapEnd /*, unsigned int maxgid*/)
+ {
+     size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable4;
+     if (!pCmapSubtable4) return false;
+     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable4);
+     // Bob H say some freeware TT fonts have version 1 (eg, CALIGULA.TTF) 
+     // so don't check subtable version. 21 Mar 2002 spec changes version to language.
+-    if (be::swap(pTable->format) != 4) return false;
++    if (table_len < sizeof(*pTable) || be::swap(pTable->format) != 4) return false;
+     const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtable4);
++    if (table_len < sizeof(*pTable4))
++        return false;
+     uint16 length = be::swap(pTable4->length);
+     if (length > table_len)
+         return false;
+     if (length < sizeof(Sfnt::CmapSubTableFormat4))
+         return false;
+     uint16 nRanges = be::swap(pTable4->seg_count_x2) >> 1;
+-    if (length < sizeof(Sfnt::CmapSubTableFormat4) + 4 * nRanges * sizeof(uint16))
++    if (!nRanges || length < sizeof(Sfnt::CmapSubTableFormat4) + 4 * nRanges * sizeof(uint16))
+         return false;
+     // check last range is properly terminated
+     uint16 chEnd = be::peek<uint16>(pTable4->end_code + nRanges - 1);
+     if (chEnd != 0xFFFF)
+         return false;
+ #if 0
+     int lastend = -1;
+     for (int i = 0; i < nRanges; ++i)
+@@ -999,17 +1001,17 @@ gid16 CmapSubtable4Lookup(const void * p
+         uint16 idRangeOffset = be::peek<uint16>(pMid += nSeg);
+ 
+         if (idRangeOffset == 0)
+             return (uint16)(idDelta + nUnicodeId); // must use modulus 2^16
+ 
+         // Look up value in glyphIdArray
+         const ptrdiff_t offset = (nUnicodeId - chStart) + (idRangeOffset >> 1) +
+                 (pMid - reinterpret_cast<const uint16 *>(pTable));
+-        if (offset * 2 >= be::swap<uint16>(pTable->length))
++        if (offset * 2 + 1 >= be::swap<uint16>(pTable->length))
+             return 0;
+         gid16 nGlyphId = be::peek<uint16>(reinterpret_cast<const uint16 *>(pTable)+offset);
+         // If this value is 0, return 0. Else add the idDelta
+         return nGlyphId ? nGlyphId + idDelta : 0;
+     }
+ 
+     return 0;
+ }
+@@ -1081,19 +1083,21 @@ unsigned int CmapSubtable4NextCodepoint(
+ /*----------------------------------------------------------------------------------------------
+     Check the Microsoft UCS-4 subtable for expected values.
+ ----------------------------------------------------------------------------------------------*/
+ bool CheckCmapSubtable12(const void *pCmapSubtable12, const void *pCmapEnd /*, unsigned int maxgid*/)
+ {
+     size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable12;
+     if (!pCmapSubtable12)  return false;
+     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable12);
+-    if (be::swap(pTable->format) != 12)
++    if (table_len < sizeof(*pTable) || be::swap(pTable->format) != 12)
+         return false;
+     const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmapSubtable12);
++    if (table_len < sizeof(*pTable12))
++        return false;
+     uint32 length = be::swap(pTable12->length);
+     if (length > table_len)
+         return false;
+     if (length < sizeof(Sfnt::CmapSubTableFormat12))
+         return false;
+     uint32 num_groups = be::swap(pTable12->num_groups);
+     if (num_groups > 0x10000000 || length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3))
+         return false;
+diff --git a/gfx/graphite2/src/inc/Code.h b/gfx/graphite2/src/inc/Code.h
+--- a/gfx/graphite2/src/inc/Code.h
++++ b/gfx/graphite2/src/inc/Code.h
+@@ -81,17 +81,17 @@ private:
+                 _modify,
+                 _delete;
+     mutable bool _own;
+ 
+     void release_buffers() throw ();
+     void failure(const status_t) throw();
+ 
+ public:
+-    static size_t estimateCodeDataOut(size_t num_bytecodes);
++    static size_t estimateCodeDataOut(size_t num_bytecodes, int nRules, int nSlots);
+ 
+     Code() throw();
+     Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
+          uint8 pre_context, uint16 rule_length, const Silf &, const Face &,
+          enum passtype pt, byte * * const _out = 0);
+     Code(const Machine::Code &) throw();
+     ~Code() throw();
+     
+@@ -107,19 +107,21 @@ public:
+     void          externalProgramMoved(ptrdiff_t) throw();
+ 
+     int32 run(Machine &m, slotref * & map) const;
+     
+     CLASS_NEW_DELETE;
+ };
+ 
+ inline
+-size_t  Machine::Code::estimateCodeDataOut(size_t n_bc)
++size_t  Machine::Code::estimateCodeDataOut(size_t n_bc, int nRules, int nSlots)
+ {
+-    return (n_bc + 1) * (sizeof(instr)+sizeof(byte));
++    // max is: all codes are instructions + 1 for each rule + max tempcopies
++    // allocate space for separate maximal code and data then merge them later
++    return (n_bc + nRules + nSlots) * sizeof(instr) + n_bc * sizeof(byte);
+ }
+ 
+ 
+ inline Machine::Code::Code() throw()
+ : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
+   _status(loaded), _constraint(false), _modify(false), _delete(false),
+   _own(false)
+ {
+diff --git a/gfx/graphite2/src/inc/Face.h b/gfx/graphite2/src/inc/Face.h
+--- a/gfx/graphite2/src/inc/Face.h
++++ b/gfx/graphite2/src/inc/Face.h
+@@ -82,17 +82,17 @@ public:
+     uint16              languageForLocale(const char * locale) const;
+ 
+     // Features
+     uint16              numFeatures() const;
+     const FeatureRef  * featureById(uint32 id) const;
+     const FeatureRef  * feature(uint16 index) const;
+ 
+     // Glyph related
+-    uint16 getGlyphMetric(uint16 gid, uint8 metric) const;
++    int32  getGlyphMetric(uint16 gid, uint8 metric) const;
+     uint16 findPseudo(uint32 uid) const;
+ 
+     // Errors
+     unsigned int        error() const { return m_error; }
+     bool                error(Error e) { m_error = e.error(); return false; }
+     unsigned int        error_context() const { return m_error; }
+     void                error_context(unsigned int errcntxt) { m_errcntxt = errcntxt; }
+ 
+diff --git a/gfx/graphite2/src/inc/GlyphFace.h b/gfx/graphite2/src/inc/GlyphFace.h
+--- a/gfx/graphite2/src/inc/GlyphFace.h
++++ b/gfx/graphite2/src/inc/GlyphFace.h
+@@ -46,17 +46,17 @@ class GlyphFace
+ public:
+     GlyphFace();
+     template<typename I>
+     GlyphFace(const Rect & bbox, const Position & adv, I first, const I last);
+ 
+     const Position    & theAdvance() const;
+     const Rect        & theBBox() const { return m_bbox; }
+     const sparse      & attrs() const { return m_attrs; }
+-    uint16              getMetric(uint8 metric) const;
++    int32               getMetric(uint8 metric) const;
+ 
+     CLASS_NEW_DELETE;
+ private:
+     Rect     m_bbox;        // bounding box metrics in design units
+     Position m_advance;     // Advance width and height in design units
+     sparse   m_attrs;
+ };
+ 
+diff --git a/gfx/graphite2/src/inc/Machine.h b/gfx/graphite2/src/inc/Machine.h
+--- a/gfx/graphite2/src/inc/Machine.h
++++ b/gfx/graphite2/src/inc/Machine.h
+@@ -179,17 +179,17 @@ inline SlotMap& Machine::slotMap() const
+     return _map;
+ }
+ 
+ inline Machine::status_t Machine::status() const throw()
+ {
+     return _status;
+ }
+ 
+-inline void Machine::check_final_stack(const int32 * const sp)
++inline void Machine::check_final_stack(const stack_t * const sp)
+ {
+     stack_t const * const base  = _stack + STACK_GUARD,
+                   * const limit = base + STACK_MAX;
+     if      (sp <  base)    _status = stack_underflow;       // This should be impossible now.
+     else if (sp >= limit)   _status = stack_overflow;        // So should this.
+     else if (sp != base)    _status = stack_not_empty;
+ }
+ 
+diff --git a/gfx/graphite2/src/inc/Pass.h b/gfx/graphite2/src/inc/Pass.h
+--- a/gfx/graphite2/src/inc/Pass.h
++++ b/gfx/graphite2/src/inc/Pass.h
+@@ -76,17 +76,17 @@ private:
+     void    dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEntry & re) const;
+     void    dumpRuleEventOutput(const FiniteStateMachine & fsm, vm::Machine & m, const Rule & r, Slot * os) const;
+     void    adjustSlot(int delta, Slot * & slot_out, SlotMap &) const;
+     bool    collisionShift(Segment *seg, int dir, json * const dbgout) const;
+     bool    collisionKern(Segment *seg, int dir, json * const dbgout) const;
+     bool    collisionFinish(Segment *seg, GR_MAYBE_UNUSED json * const dbgout) const;
+     bool    resolveCollisions(Segment *seg, Slot *slot, Slot *start, ShiftCollider &coll, bool isRev,
+                      int dir, bool &moved, bool &hasCol, json * const dbgout) const;
+-    float   resolveKern(Segment *seg, Slot *slot, Slot *start, KernCollider &coll, int dir,
++    float   resolveKern(Segment *seg, Slot *slot, Slot *start, int dir,
+                      float &ymin, float &ymax, json *const dbgout) const;
+ 
+     const Silf        * m_silf;
+     uint16            * m_cols;
+     Rule              * m_rules; // rules
+     RuleEntry         * m_ruleMap;
+     uint16            * m_startStates; // prectxt length
+     uint16            * m_transitions;
+diff --git a/gfx/graphite2/src/inc/Rule.h b/gfx/graphite2/src/inc/Rule.h
+--- a/gfx/graphite2/src/inc/Rule.h
++++ b/gfx/graphite2/src/inc/Rule.h
+@@ -97,17 +97,17 @@ bool State::empty() const
+     return rules_end == rules;
+ }
+ 
+ 
+ class SlotMap
+ {
+ public:
+   enum {MAX_SLOTS=64};
+-  SlotMap(Segment & seg, uint8 direction);
++  SlotMap(Segment & seg, uint8 direction, int maxSize);
+   
+   Slot       * * begin();
+   Slot       * * end();
+   size_t         size() const;
+   unsigned short context() const;
+   void           reset(Slot &, unsigned short);
+   
+   Slot * const & operator[](int n) const;
+@@ -116,23 +116,25 @@ public:
+   void           collectGarbage(Slot *& aSlot);
+ 
+   Slot         * highwater() { return m_highwater; }
+   void           highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
+   bool           highpassed() const { return m_highpassed; }
+   void           highpassed(bool v) { m_highpassed = v; }
+ 
+   uint8          dir() const { return m_dir; }
++  int            decMax() { return --m_maxSize; }
+ 
+   Segment &    segment;
+ private:
+   Slot         * m_slot_map[MAX_SLOTS+1];
+   unsigned short m_size;
+   unsigned short m_precontext;
+   Slot         * m_highwater;
++  int            m_maxSize;
+   uint8          m_dir;
+   bool           m_highpassed;
+ };
+ 
+ 
+ class FiniteStateMachine
+ {
+ public:
+@@ -237,18 +239,19 @@ void FiniteStateMachine::Rules::accumula
+       return;
+     }
+   }
+   while (rre != rrend && out != lrend) { *out++ = *rre++; }
+   m_end = out;
+ }
+ 
+ inline
+-SlotMap::SlotMap(Segment & seg, uint8 direction)
+-: segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_dir(direction), m_highpassed(false)
++SlotMap::SlotMap(Segment & seg, uint8 direction, int maxSize)
++: segment(seg), m_size(0), m_precontext(0), m_highwater(0),
++    m_maxSize(maxSize), m_dir(direction), m_highpassed(false)
+ {
+     m_slot_map[0] = 0;
+ }
+ 
+ inline
+ Slot * * SlotMap::begin()
+ {
+   return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
+diff --git a/gfx/graphite2/src/inc/Segment.h b/gfx/graphite2/src/inc/Segment.h
+--- a/gfx/graphite2/src/inc/Segment.h
++++ b/gfx/graphite2/src/inc/Segment.h
+@@ -35,17 +35,17 @@ of the License or (at your option) any l
+ #include "inc/FeatureVal.h"
+ #include "inc/GlyphCache.h"
+ #include "inc/GlyphFace.h"
+ #include "inc/Slot.h"
+ #include "inc/Position.h"
+ #include "inc/List.h"
+ #include "inc/Collider.h"
+ 
+-#define MAX_SEG_GROWTH_FACTOR  256
++#define MAX_SEG_GROWTH_FACTOR  64
+ 
+ namespace graphite2 {
+ 
+ typedef Vector<Features>        FeatureList;
+ typedef Vector<Slot *>          SlotRope;
+ typedef Vector<int16 *>         AttributeRope;
+ typedef Vector<SlotJustify *>   JustifyRope;
+ 
+@@ -154,17 +154,17 @@ public:
+     int8 getSlotBidiClass(Slot *s) const;
+     void doMirror(uint16 aMirror);
+     Slot *addLineEnd(Slot *nSlot);
+     void delLineEnd(Slot *s);
+     bool hasJustification() const { return m_justifies.size() != 0; }
+     void reverseSlots();
+ 
+     bool isWhitespace(const int cid) const;
+-    bool hasCollisionInfo() const { return (m_flags & SEG_HASCOLLISIONS); }
++    bool hasCollisionInfo() const { return (m_flags & SEG_HASCOLLISIONS) && m_collisions; }
+     SlotCollision *collisionInfo(const Slot *s) const { return m_collisions ? m_collisions + s->index() : 0; }
+     CLASS_NEW_DELETE
+ 
+ public:       //only used by: GrSegment* makeAndInitialize(const GrFont *font, const GrFace *face, uint32 script, const FeaturesHandle& pFeats/*must not be IsNull*/, encform enc, const void* pStart, size_t nChars, int dir);
+     bool read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void*pStart, size_t nChars);
+     void finalise(const Font *font, bool reverse=false);
+     float justify(Slot *pSlot, const Font *font, float width, enum justFlags flags, Slot *pFirst, Slot *pLast);
+     bool initCollisions();
+diff --git a/gfx/graphite2/src/inc/Slot.h b/gfx/graphite2/src/inc/Slot.h
+--- a/gfx/graphite2/src/inc/Slot.h
++++ b/gfx/graphite2/src/inc/Slot.h
+@@ -92,17 +92,17 @@ public:
+     void adjKern(const Position &pos) { m_shift = m_shift + pos; m_advance = m_advance + pos; }
+     void origin(const Position &pos) { m_position = pos + m_shift; }
+     void originate(int ind) { m_original = ind; }
+     int original() const { return m_original; }
+     void before(int ind) { m_before = ind; }
+     void after(int ind) { m_after = ind; }
+     bool isBase() const { return (!m_parent); }
+     void update(int numSlots, int numCharInfo, Position &relpos);
+-    Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal);
++    Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal, int depth = 0);
+     bool isDeleted() const { return (m_flags & DELETED) ? true : false; }
+     void markDeleted(bool state) { if (state) m_flags |= DELETED; else m_flags &= ~DELETED; }
+     bool isCopied() const { return (m_flags & COPIED) ? true : false; }
+     void markCopied(bool state) { if (state) m_flags |= COPIED; else m_flags &= ~COPIED; }
+     bool isPositioned() const { return (m_flags & POSITIONED) ? true : false; }
+     void markPositioned(bool state) { if (state) m_flags |= POSITIONED; else m_flags &= ~POSITIONED; }
+     bool isInsertBefore() const { return !(m_flags & INSERTED); }
+     uint8 getBidiLevel() const { return m_bidiLevel; }
+@@ -123,20 +123,19 @@ public:
+     Position attachOffset() const { return m_attach - m_with; }
+     Slot* firstChild() const { return m_child; }
+     void firstChild(Slot *ap) { m_child = ap; }
+     bool child(Slot *ap);
+     Slot* nextSibling() const { return m_sibling; }
+     void nextSibling(Slot *ap) { m_sibling = ap; }
+     bool sibling(Slot *ap);
+     bool removeChild(Slot *ap);
+-    bool removeSibling(Slot *ap);
+     int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel, bool rtl);
+     void positionShift(Position a) { m_position += a; }
+-    void floodShift(Position adj);
++    void floodShift(Position adj, int depth = 0);
+     float just() const { return m_just; }
+     void just(float j) { m_just = j; }
+     Slot *nextInCluster(const Slot *s) const;
+     bool isChildOf(const Slot *base) const;
+ 
+     CLASS_NEW_DELETE
+ 
+ private:
+diff --git a/gfx/graphite2/src/inc/UtfCodec.h b/gfx/graphite2/src/inc/UtfCodec.h
+--- a/gfx/graphite2/src/inc/UtfCodec.h
++++ b/gfx/graphite2/src/inc/UtfCodec.h
+@@ -35,16 +35,17 @@ typedef uint32  uchar_t;
+ 
+ template <int N>
+ struct _utf_codec
+ {
+     typedef uchar_t codeunit_t;
+ 
+     static void     put(codeunit_t * cp, const uchar_t , int8 & len) throw();
+     static uchar_t  get(const codeunit_t * cp, int8 & len) throw();
++    static bool     validate(const codeunit_t * s, const codeunit_t * e) throw();
+ };
+ 
+ 
+ template <>
+ struct _utf_codec<32>
+ {
+ private:
+     static const uchar_t    limit = 0x110000;
+@@ -58,16 +59,22 @@ public:
+     }
+ 
+     inline
+     static uchar_t get(const codeunit_t * cp, int8 & l) throw()
+     {
+         if (cp[0] < limit)  { l = 1;  return cp[0]; }
+         else                { l = -1; return 0xFFFD; }
+     }
++
++    inline
++    static bool validate(codeunit_t * s, codeunit_t * e) throw()
++    {
++        return e > s;
++    }
+ };
+ 
+ 
+ template <>
+ struct _utf_codec<16>
+ {
+ private:
+     static const int32  lead_offset      = 0xD800 - (0x10000 >> 10);
+@@ -88,22 +95,31 @@ public:
+     }
+ 
+     inline
+     static uchar_t get(const codeunit_t * cp, int8 & l) throw()
+     {
+         const uint32    uh = cp[0];
+         l = 1;
+ 
+-        if (0xD800 > uh || uh > 0xDFFF) { return uh; }
++        if (uh < 0xD800|| uh > 0xDFFF) { return uh; }
+         const uint32 ul = cp[1];
+-        if (uh > 0xDBFF || 0xDC00 > ul || ul > 0xDFFF) { l = -1; return 0xFFFD; }
++        if (uh > 0xDBFF || ul < 0xDC00 || ul > 0xDFFF) { l = -1; return 0xFFFD; }
+         ++l;
+         return (uh<<10) + ul + surrogate_offset;
+     }
++
++    inline
++    static bool validate(codeunit_t * s, codeunit_t * e) throw()
++    {
++        const ptrdiff_t n = e-s;
++        if (n <= 0) return n == 0;
++        const uint32 u = *(s+(n-1)); // Get the last codepoint
++        return (u < 0xD800 || u > 0xDBFF);
++    }
+ };
+ 
+ 
+ template <>
+ struct _utf_codec<8>
+ {
+ private:
+     static const int8 sz_lut[16];
+@@ -143,16 +159,34 @@ public:
+ 
+         if (l != seq_sz || toolong)
+         {
+             l = -l;
+             return 0xFFFD;
+         }
+         return u;
+     }
++
++    inline
++    static bool validate(codeunit_t * s, codeunit_t * e) throw()
++    {
++        const ptrdiff_t n = e-s;
++        if (n <= 0) return n == 0;
++        s += (n-1);
++        if (*s < 0x80) return true;
++        if (*s >= 0xC0) return false;
++        if (n == 1) return true;
++        if (*--s < 0x80) return true;
++        if (*s >= 0xe0) return false;
++        if (n == 2 || *s >= 0xC0) return true;
++        if (*--s < 0x80) return true;
++        if (*s >= 0xF0) return false;
++        return true;
++    }
++
+ };
+ 
+ 
+ template <typename C>
+ class _utf_iterator
+ {
+     typedef _utf_codec<sizeof(C)*8> codec;
+ 
+@@ -195,16 +229,21 @@ public:
+ 
+ template <typename C>
+ struct utf
+ {
+     typedef typename _utf_codec<sizeof(C)*8>::codeunit_t codeunit_t;
+ 
+     typedef _utf_iterator<C>        iterator;
+     typedef _utf_iterator<const C>  const_iterator;
++
++    inline
++    static bool validate(codeunit_t * s, codeunit_t * e) throw() {
++        return _utf_codec<sizeof(C)*8>::validate(s,e);
++    }
+ };
+ 
+ 
+ typedef utf<uint32> utf32;
+ typedef utf<uint16> utf16;
+ typedef utf<uint8>  utf8;
+ 
+ } // namespace graphite2
+diff --git a/gfx/graphite2/src/inc/opcode_table.h b/gfx/graphite2/src/inc/opcode_table.h
+--- a/gfx/graphite2/src/inc/opcode_table.h
++++ b/gfx/graphite2/src/inc/opcode_table.h
+@@ -113,13 +113,13 @@ static const opcode_t opcode_table[] =
+     {{NILOP,NILOP},                                 0, "PUT_SUBS3"},
+     {{do_(put_glyph), NILOP},                       2, "PUT_GLYPH"},                // output_class output_class
+     {{do2(push_glyph_attr)},                        3, "PUSH_GLYPH_ATTR"},          // gattrnum gattrnum slot
+     {{do2(push_att_to_glyph_attr)},                 3, "PUSH_ATT_TO_GLYPH_ATTR"},   // gattrnum gattrnum slot
+     {{do2(bor)},                                    0, "BITOR"},
+     {{do2(band)},                                   0, "BITAND"},
+     {{do2(bnot)},                                   0, "BITNOT"},   // 0x40
+     {{do2(setbits)},                                4, "BITSET"},
+-    {{do2(set_feat)},                               2, "SET_FEAT"},
++    {{do_(set_feat), NILOP},                        2, "SET_FEAT"},                 // featidx slot
+     // private opcodes for internal use only, comes after all other on disk opcodes.
+     {{do_(temp_copy), NILOP},                       0, "TEMP_COPY"}
+ };
+ 
+diff --git a/gfx/graphite2/src/inc/opcodes.h b/gfx/graphite2/src/inc/opcodes.h
+--- a/gfx/graphite2/src/inc/opcodes.h
++++ b/gfx/graphite2/src/inc/opcodes.h
+@@ -62,17 +62,18 @@ of the License or (at your option) any l
+ //        ip        = The current instruction pointer
+ //        endPos    = Position of advance of last cluster
+ //        dir       = writing system directionality of the font
+      
+ 
+ // #define NOT_IMPLEMENTED     assert(false)
+ #define NOT_IMPLEMENTED
+ 
+-#define binop(op)           const int32 a = pop(); *sp = int32(*sp) op a
++#define binop(op)           const uint32 a = pop(); *sp = uint32(*sp) op a
++#define sbinop(op)          const int32 a = pop(); *sp = int32(*sp) op a
+ #define use_params(n)       dp += n
+ 
+ #define declare_params(n)   const byte * param = dp; \
+                             use_params(n);
+ 
+ #define push(n)             { *++sp = n; }
+ #define pop()               (*sp--)
+ #define slotat(x)           (map[(x)])
+@@ -125,17 +126,17 @@ STARTOP(sub)
+ ENDOP
+ 
+ STARTOP(mul)
+     binop(*);
+ ENDOP
+ 
+ STARTOP(div_)
+     if (*sp == 0) DIE;
+-    binop(/);
++    sbinop(/);
+ ENDOP
+ 
+ STARTOP(min_)
+     const int32 a = pop(), b = *sp;
+     if (a < b) *sp = a;
+ ENDOP
+ 
+ STARTOP(max_)
+@@ -176,29 +177,29 @@ STARTOP(equal)
+     binop(==);
+ ENDOP
+ 
+ STARTOP(not_eq_)
+     binop(!=);
+ ENDOP
+ 
+ STARTOP(less)
+-    binop(<);
++    sbinop(<);
+ ENDOP
+ 
+ STARTOP(gtr)
+-    binop(>);
++    sbinop(>);
+ ENDOP
+ 
+ STARTOP(less_eq)
+-    binop(<=);
++    sbinop(<=);
+ ENDOP
+ 
+ STARTOP(gtr_eq)
+-    binop(>=);
++    sbinop(>=);
+ ENDOP
+ 
+ STARTOP(next)
+     if (map - &smap[0] >= int(smap.size())) DIE
+     if (is)
+     {
+         if (is == smap.highwater())
+             smap.highpassed(true);
+@@ -237,17 +238,17 @@ STARTOP(put_subs_8bit_obs)
+         index = seg.findClassIndex(input_class, slot->gid());
+         is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
+     }
+ ENDOP
+ 
+ STARTOP(put_copy)
+     declare_params(1);
+     const int  slot_ref = int8(*param);
+-    if (is)
++    if (is && !is->isDeleted())
+     {
+         slotref ref = slotat(slot_ref);
+         if (ref && ref != is)
+         {
+             int16 *tempUserAttrs = is->userAttrs();
+             if (is->attachedTo() || is->firstChild()) DIE
+             Slot *prev = is->prev();
+             Slot *next = is->next();
+@@ -262,16 +263,17 @@ STARTOP(put_copy)
+                 is->attachedTo()->child(is);
+         }
+         is->markCopied(false);
+         is->markDeleted(false);
+     }
+ ENDOP
+ 
+ STARTOP(insert)
++    if (smap.decMax() <= 0) DIE;
+     Slot *newSlot = seg.newSlot();
+     if (!newSlot) DIE;
+     Slot *iss = is;
+     while (iss && iss->isDeleted()) iss = iss->next();
+     if (!iss)
+     {
+         if (seg.last())
+         {
+@@ -550,31 +552,31 @@ ENDOP
+ 
+ STARTOP(iattr_add)
+     declare_params(2);
+     const attrCode      slat = attrCode(uint8(param[0]));
+     const size_t        idx  = uint8(param[1]);
+     const          int  val  = int(pop());
+     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+     {
+-        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
++        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+         flags |= POSITIONED;
+     }
+     int res = is->getAttr(&seg, slat, idx);
+     is->setAttr(&seg, slat, idx, val + res, smap);
+ ENDOP
+ 
+ STARTOP(iattr_sub)
+     declare_params(2);
+     const attrCode      slat = attrCode(uint8(param[0]));
+     const size_t        idx  = uint8(param[1]);
+     const          int  val  = int(pop());
+     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
+     {
+-        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
++        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
+         flags |= POSITIONED;
+     }
+     int res = is->getAttr(&seg, slat, idx);
+     is->setAttr(&seg, slat, idx, res - val, smap);
+ ENDOP
+ 
+ STARTOP(push_proc_state)
+     use_params(1);
+
diff --git a/gnu/packages/patches/icecat-update-graphite2-pt2.patch b/gnu/packages/patches/icecat-update-graphite2-pt2.patch
deleted file mode 100644
index 8acde75d6c..0000000000
--- a/gnu/packages/patches/icecat-update-graphite2-pt2.patch
+++ /dev/null
@@ -1,861 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/ec9cff7bb543
-
-# HG changeset patch
-# User Jonathan Kew <jkew@mozilla.com>
-# Date 1456760339 0
-# Node ID ec9cff7bb5439b2b4c1249ff9376d07a80172c27
-# Parent  6f4d5130238790fa5810c76ffeb9eccc65efa8c9
-Bug 1248876 - Update graphite2 to upstream release 1.3.6. r=jrmuizel a=sledru
-
-diff --git a/gfx/graphite2/README.mozilla b/gfx/graphite2/README.mozilla
---- a/gfx/graphite2/README.mozilla
-+++ b/gfx/graphite2/README.mozilla
-@@ -1,7 +1,3 @@
--This directory contains the Graphite2 library release 1.3.5 from
--https://github.com/silnrsi/graphite/releases/download/1.3.5/graphite2-minimal-1.3.5.tgz
-+This directory contains the Graphite2 library release 1.3.6 from
-+https://github.com/silnrsi/graphite/releases/download/1.3.6/graphite-minimal-1.3.6.tgz
- See gfx/graphite2/moz-gr-update.sh for update procedure.
--
--Also includes two post-1.3.5 fixes:
--a8b3ac2aed0eb132cd80efe7de88f8153e73c829
--e569e28d83491fedb31b9220493f3c07f6ec6d80
-diff --git a/gfx/graphite2/include/graphite2/Font.h b/gfx/graphite2/include/graphite2/Font.h
---- a/gfx/graphite2/include/graphite2/Font.h
-+++ b/gfx/graphite2/include/graphite2/Font.h
-@@ -25,17 +25,17 @@
-     either version 2 of the License or (at your option) any later version.
- */
- #pragma once
- 
- #include "graphite2/Types.h"
- 
- #define GR2_VERSION_MAJOR   1
- #define GR2_VERSION_MINOR   3
--#define GR2_VERSION_BUGFIX  5
-+#define GR2_VERSION_BUGFIX  6
- 
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- 
- typedef struct gr_face          gr_face;
- typedef struct gr_font          gr_font;
-diff --git a/gfx/graphite2/moz-gr-update.sh b/gfx/graphite2/moz-gr-update.sh
---- a/gfx/graphite2/moz-gr-update.sh
-+++ b/gfx/graphite2/moz-gr-update.sh
-@@ -14,17 +14,17 @@
- RELEASE=$1
- 
- if [ "x$RELEASE" == "x" ]
- then
-     echo "Must provide the version number to be used."
-     exit 1
- fi
- 
--TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite2-minimal-$RELEASE.tgz"
-+TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite-minimal-$RELEASE.tgz"
- 
- foo=`basename $0`
- TMPFILE=`mktemp -t ${foo}` || exit 1
- 
- curl -L "$TARBALL" -o "$TMPFILE"
- tar -x -z -C gfx/graphite2/ --strip-components 1 -f "$TMPFILE" || exit 1
- rm "$TMPFILE"
- 
-diff --git a/gfx/graphite2/src/CmapCache.cpp b/gfx/graphite2/src/CmapCache.cpp
---- a/gfx/graphite2/src/CmapCache.cpp
-+++ b/gfx/graphite2/src/CmapCache.cpp
-@@ -33,43 +33,43 @@ of the License or (at your option) any l
- 
- 
- using namespace graphite2;
- 
- const void * bmp_subtable(const Face::Table & cmap)
- {
-     const void * stbl;
-     if (!cmap.size()) return 0;
--    if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap.size())
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap.size())
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap.size())
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap.size())
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap.size()))
-+    if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap + cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap + cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap + cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap + cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap + cmap.size()))
-         return stbl;
-     return 0;
- }
- 
- const void * smp_subtable(const Face::Table & cmap)
- {
-     const void * stbl;
-     if (!cmap.size()) return 0;
--    if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap.size())
--     || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap.size()))
-+    if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap + cmap.size())
-+     || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap + cmap.size()))
-         return stbl;
-     return 0;
- }
- 
- template <unsigned int (*NextCodePoint)(const void *, unsigned int, int *),
-           uint16 (*LookupCodePoint)(const void *, unsigned int, int)>
- bool cache_subtable(uint16 * blocks[], const void * cst, const unsigned int limit)
- {
-     int rangeKey = 0;
-     uint32          codePoint = NextCodePoint(cst, 0, &rangeKey),
-                     prevCodePoint = 0;
--    while (codePoint != limit)
-+    while (codePoint < limit)
-     {
-         unsigned int block = codePoint >> 8;
-         if (!blocks[block])
-         {
-             blocks[block] = grzeroalloc<uint16>(0x100);
-             if (!blocks[block])
-                 return false;
-         }
-diff --git a/gfx/graphite2/src/Code.cpp b/gfx/graphite2/src/Code.cpp
---- a/gfx/graphite2/src/Code.cpp
-+++ b/gfx/graphite2/src/Code.cpp
-@@ -79,18 +79,19 @@ struct context
- 
- 
- class Machine::Code::decoder
- {
- public:
-     struct limits;
-     struct analysis
-     {
-+        static const int NUMCONTEXTS = 256;
-         uint8     slotref;
--        context   contexts[256];
-+        context   contexts[NUMCONTEXTS];
-         byte      max_ref;
-         
-         analysis() : slotref(0), max_ref(0) {};
-         void set_ref(int index, bool incinsert=false) throw();
-         void set_noref(int index) throw();
-         void set_changed(int index) throw();
- 
-     };
-@@ -363,29 +364,33 @@ opcode Machine::Code::decoder::fetch_opc
-             break;
-         case ATTR_SET :
-         case ATTR_ADD :
-         case ATTR_SUB :
-         case ATTR_SET_SLOT :
-             if (--_stack_depth < 0)
-                 failure(underfull_stack);
-             valid_upto(gr_slatMax, bc[0]);
-+            if (attrCode(bc[0]) == gr_slatUserDefn)     // use IATTR for user attributes
-+                failure(out_of_range_data);
-             test_context();
-             break;
-         case IATTR_SET_SLOT :
-             if (--_stack_depth < 0)
-                 failure(underfull_stack);
-             if (valid_upto(gr_slatMax, bc[0]))
-                 valid_upto(_max.attrid[bc[0]], bc[1]);
-             test_context();
-             break;
-         case PUSH_SLOT_ATTR :
-             ++_stack_depth;
-             valid_upto(gr_slatMax, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-+            if (attrCode(bc[0]) == gr_slatUserDefn)     // use IATTR for user attributes
-+                failure(out_of_range_data);
-             break;
-         case PUSH_GLYPH_ATTR_OBS :
-             ++_stack_depth;
-             valid_upto(_max.glyf_attrs, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-             break;
-         case PUSH_GLYPH_METRIC :
-             ++_stack_depth;
-@@ -656,24 +661,24 @@ bool Machine::Code::decoder::validate_op
-         return false;
-     }
-     return true;
- }
- 
- 
- bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) const throw()
- {
--    const bool t = x < limit;
-+    const bool t = (limit != 0) && (x < limit);
-     if (!t) failure(out_of_range_data);
-     return t;
- }
- 
- bool Machine::Code::decoder::test_context() const throw()
- {
--    if (_pre_context >= _rule_length)
-+    if (_pre_context >= _rule_length || _analysis.slotref >= analysis::NUMCONTEXTS - 1)
-     {
-         failure(out_of_range_data);
-         return false;
-     }
-     return true;
- }
- 
- inline 
-@@ -681,34 +686,34 @@ void Machine::Code::failure(const status
-     release_buffers();
-     _status = s;
- }
- 
- 
- inline
- void Machine::Code::decoder::analysis::set_ref(int index, bool incinsert) throw() {
-     if (incinsert && contexts[slotref].flags.inserted) --index;
--    if (index + slotref < 0) return;
-+    if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
-     contexts[index + slotref].flags.referenced = true;
-     if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
- }
- 
- 
- inline
- void Machine::Code::decoder::analysis::set_noref(int index) throw() {
-     if (contexts[slotref].flags.inserted) --index;
--    if (index + slotref < 0) return;
-+    if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
-     if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
- }
- 
- 
- inline
- void Machine::Code::decoder::analysis::set_changed(int index) throw() {
-     if (contexts[slotref].flags.inserted) --index;
--    if (index + slotref < 0) return;
-+    if (index + slotref < 0 || index + slotref >= NUMCONTEXTS) return;
-     contexts[index + slotref].flags.changed = true;
-     if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
- }
- 
- 
- void Machine::Code::release_buffers() throw()
- {
-     if (_own)
-diff --git a/gfx/graphite2/src/GlyphCache.cpp b/gfx/graphite2/src/GlyphCache.cpp
---- a/gfx/graphite2/src/GlyphCache.cpp
-+++ b/gfx/graphite2/src/GlyphCache.cpp
-@@ -260,17 +260,17 @@ GlyphCache::Loader::Loader(const Face & 
-         _head = Face::Table();
-         return;
-     }
- 
-     if (!dumb_font)
-     {
-         if ((m_pGlat = Face::Table(face, Tag::Glat, 0x00030000)) == NULL
-             || (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
--            || m_pGloc.size() < 6)
-+            || m_pGloc.size() < 8)
-         {
-             _head = Face::Table();
-             return;
-         }
-         const byte    * p = m_pGloc;
-         int       version = be::read<uint32>(p);
-         const uint16    flags = be::read<uint16>(p);
-         _num_attrs = be::read<uint16>(p);
-diff --git a/gfx/graphite2/src/Pass.cpp b/gfx/graphite2/src/Pass.cpp
---- a/gfx/graphite2/src/Pass.cpp
-+++ b/gfx/graphite2/src/Pass.cpp
-@@ -233,17 +233,17 @@ bool Pass::readRules(const byte * rule_m
-     m_codes = new Code [m_numRules*2];
-     const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data);
-     m_progs = gralloc<byte>(prog_pool_sz);
-     byte * prog_pool_free = m_progs,
-          * prog_pool_end  = m_progs + prog_pool_sz;
-     if (e.test(!(m_rules && m_codes && m_progs), E_OUTOFMEM)) return face.error(e);
- 
-     Rule * r = m_rules + m_numRules - 1;
--    for (size_t n = m_numRules; n; --n, --r, ac_end = ac_begin, rc_end = rc_begin)
-+    for (size_t n = m_numRules; r >= m_rules; --n, --r, ac_end = ac_begin, rc_end = rc_begin)
-     {
-         face.error_context((face.error_context() & 0xFFFF00) + EC_ARULE + ((n - 1) << 24));
-         r->preContext = *--precontext;
-         r->sort       = be::peek<uint16>(--sort_key);
- #ifndef NDEBUG
-         r->rule_idx   = n - 1;
- #endif
-         if (r->sort > 63 || r->preContext >= r->sort || r->preContext > m_maxPreCtxt || r->preContext < m_minPreCtxt)
-@@ -405,16 +405,17 @@ bool Pass::runGraphite(vm::Machine & m, 
-         json::closer rules_array_closer(fsm.dbgout);
- #endif
- 
-         m.slotMap().highwater(currHigh);
-         int lc = m_iMaxLoop;
-         do
-         {
-             findNDoRule(s, m, fsm);
-+            if (m.status() != Machine::finished) return false;
-             if (s && (s == m.slotMap().highwater() || m.slotMap().highpassed() || --lc == 0)) {
-                 if (!lc)
-                     s = m.slotMap().highwater();
-                 lc = m_iMaxLoop;
-                 if (s)
-                     m.slotMap().highwater(s->next());
-             }
-         } while (s);
-@@ -495,17 +496,22 @@ void Pass::findNDoRule(Slot * & slot, Ma
- {
-     assert(slot);
- 
-     if (runFSM(fsm, slot))
-     {
-         // Search for the first rule which passes the constraint
-         const RuleEntry *        r = fsm.rules.begin(),
-                         * const re = fsm.rules.end();
--        while (r != re && !testConstraint(*r->rule, m)) ++r;
-+        while (r != re && !testConstraint(*r->rule, m))
-+        {
-+            ++r;
-+            if (m.status() != Machine::finished)
-+                return;
-+        }
- 
- #if !defined GRAPHITE2_NTRACING
-         if (fsm.dbgout)
-         {
-             if (fsm.rules.size() != 0)
-             {
-                 *fsm.dbgout << json::item << json::object;
-                 dumpRuleEventConsidered(fsm, *r);
-@@ -530,16 +536,17 @@ void Pass::findNDoRule(Slot * & slot, Ma
-             }
-         }
-         else
- #endif
-         {
-             if (r != re)
-             {
-                 const int adv = doAction(r->rule->action, slot, m);
-+                if (m.status() != Machine::finished) return;
-                 if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot);
-                 adjustSlot(adv, slot, fsm.slots);
-                 return;
-             }
-         }
-     }
- 
-     slot = slot->next();
-diff --git a/gfx/graphite2/src/Segment.cpp b/gfx/graphite2/src/Segment.cpp
---- a/gfx/graphite2/src/Segment.cpp
-+++ b/gfx/graphite2/src/Segment.cpp
-@@ -205,18 +205,23 @@ Slot *Segment::newSlot()
- void Segment::freeSlot(Slot *aSlot)
- {
-     if (m_last == aSlot) m_last = aSlot->prev();
-     if (m_first == aSlot) m_first = aSlot->next();
-     if (aSlot->attachedTo())
-         aSlot->attachedTo()->removeChild(aSlot);
-     while (aSlot->firstChild())
-     {
--        aSlot->firstChild()->attachTo(NULL);
--        aSlot->removeChild(aSlot->firstChild());
-+        if (aSlot->firstChild()->attachedTo() == aSlot)
-+        {
-+            aSlot->firstChild()->attachTo(NULL);
-+            aSlot->removeChild(aSlot->firstChild());
-+        }
-+        else
-+            aSlot->firstChild(NULL);
-     }
-     // reset the slot incase it is reused
-     ::new (aSlot) Slot(aSlot->userAttrs());
-     memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
-     // Update generation counter for debug
- #if !defined GRAPHITE2_NTRACING
-     if (m_face->logger())
-         ++aSlot->userAttrs()[m_silf->numUser()];
-diff --git a/gfx/graphite2/src/Slot.cpp b/gfx/graphite2/src/Slot.cpp
---- a/gfx/graphite2/src/Slot.cpp
-+++ b/gfx/graphite2/src/Slot.cpp
-@@ -192,16 +192,18 @@ int32 Slot::clusterMetric(const Segment 
- #define SLOTGETCOLATTR(x) { SlotCollision *c = seg->collisionInfo(this); return c ? int(c-> x) : 0; }
- 
- int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
- {
-     if (ind == gr_slatUserDefnV1)
-     {
-         ind = gr_slatUserDefn;
-         subindex = 0;
-+        if (seg->numAttrs() == 0)
-+            return 0;
-     }
-     else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
-     {
-         int indx = ind - gr_slatJStretch;
-         return getJustify(seg, indx / 5, indx % 5);
-     }
- 
-     switch (ind)
-@@ -269,16 +271,18 @@ int Slot::getAttr(const Segment *seg, at
-         break; }
- 
- void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
- {
-     if (ind == gr_slatUserDefnV1)
-     {
-         ind = gr_slatUserDefn;
-         subindex = 0;
-+        if (seg->numAttrs() == 0)
-+            return;
-     }
-     else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
-     {
-         int indx = ind - gr_slatJStretch;
-         return setJustify(seg, indx / 5, indx % 5, value);
-     }
- 
-     switch (ind)
-@@ -416,32 +420,32 @@ bool Slot::sibling(Slot *ap)
- }
- 
- bool Slot::removeChild(Slot *ap)
- {
-     if (this == ap || !m_child) return false;
-     else if (ap == m_child)
-     {
-         Slot *nSibling = m_child->nextSibling();
--        m_child->sibling(NULL);
-+        m_child->removeSibling(nSibling);
-         m_child = nSibling;
-         return true;
-     }
-     else
-         return m_child->removeSibling(ap);
-     return true;
- }
- 
- bool Slot::removeSibling(Slot *ap)
- {
-     if (this == ap || !m_sibling) return false;
-     else if (ap == m_sibling)
-     {
-         m_sibling = m_sibling->nextSibling();
--        ap->sibling(NULL);
-+        if (m_sibling) ap->removeSibling(m_sibling);
-         return true;
-     }
-     else
-         return m_sibling->removeSibling(ap);
-     return true;
- }
- 
- void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
-diff --git a/gfx/graphite2/src/TtfUtil.cpp b/gfx/graphite2/src/TtfUtil.cpp
---- a/gfx/graphite2/src/TtfUtil.cpp
-+++ b/gfx/graphite2/src/TtfUtil.cpp
-@@ -884,18 +884,19 @@ const void * FindCmapSubtable(const void
-     }
- 
-     return 0;
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Check the Microsoft Unicode subtable for expected values
- ----------------------------------------------------------------------------------------------*/
--bool CheckCmapSubtable4(const void * pCmapSubtable4, size_t table_len /*, unsigned int maxgid*/)
-+bool CheckCmapSubtable4(const void * pCmapSubtable4, const void * pCmapEnd /*, unsigned int maxgid*/)
- {
-+    size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable4;
-     if (!pCmapSubtable4) return false;
-     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable4);
-     // Bob H say some freeware TT fonts have version 1 (eg, CALIGULA.TTF) 
-     // so don't check subtable version. 21 Mar 2002 spec changes version to language.
-     if (be::swap(pTable->format) != 4) return false;
-     const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtable4);
-     uint16 length = be::swap(pTable4->length);
-     if (length > table_len)
-@@ -1044,17 +1045,17 @@ unsigned int CmapSubtable4NextCodepoint(
-             *pRangeKey = nRange - 1;
-         return 0xFFFF;
-     }
- 
-     int iRange = (pRangeKey) ? *pRangeKey : 0;
-     // Just in case we have a bad key:
-     while (iRange > 0 && be::peek<uint16>(pStartCode + iRange) > nUnicodePrev)
-         iRange--;
--    while (be::peek<uint16>(pTable->end_code + iRange) < nUnicodePrev)
-+    while (iRange < nRange - 1 && be::peek<uint16>(pTable->end_code + iRange) < nUnicodePrev)
-         iRange++;
- 
-     // Now iRange is the range containing nUnicodePrev.
-     unsigned int nStartCode = be::peek<uint16>(pStartCode + iRange);
-     unsigned int nEndCode = be::peek<uint16>(pTable->end_code + iRange);
- 
-     if (nStartCode > nUnicodePrev)
-         // Oops, nUnicodePrev is not in the cmap! Adjust so we get a reasonable
-@@ -1069,36 +1070,37 @@ unsigned int CmapSubtable4NextCodepoint(
-         return nUnicodePrev + 1;
-     }
- 
-     // Otherwise the next codepoint is the first one in the next range.
-     // There is guaranteed to be a next range because there must be one that
-     // ends with 0xFFFF.
-     if (pRangeKey)
-         *pRangeKey = iRange + 1;
--    return be::peek<uint16>(pStartCode + iRange + 1);
-+    return (iRange + 1 >= nRange) ? 0xFFFF : be::peek<uint16>(pStartCode + iRange + 1);
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Check the Microsoft UCS-4 subtable for expected values.
- ----------------------------------------------------------------------------------------------*/
--bool CheckCmapSubtable12(const void *pCmapSubtable12, size_t table_len /*, unsigned int maxgid*/)
-+bool CheckCmapSubtable12(const void *pCmapSubtable12, const void *pCmapEnd /*, unsigned int maxgid*/)
- {
-+    size_t table_len = (const byte *)pCmapEnd - (const byte *)pCmapSubtable12;
-     if (!pCmapSubtable12)  return false;
-     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable12);
-     if (be::swap(pTable->format) != 12)
-         return false;
-     const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmapSubtable12);
-     uint32 length = be::swap(pTable12->length);
-     if (length > table_len)
-         return false;
-     if (length < sizeof(Sfnt::CmapSubTableFormat12))
-         return false;
-     uint32 num_groups = be::swap(pTable12->num_groups);
--    if (length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3))
-+    if (num_groups > 0x10000000 || length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3))
-         return false;
- #if 0
-     for (unsigned int i = 0; i < num_groups; ++i)
-     {
-         if (be::swap(pTable12->group[i].end_char_code)  - be::swap(pTable12->group[i].start_char_code) + be::swap(pTable12->group[i].start_glyph_id) > maxgid)
-             return false;
-         if (i > 0 && be::swap(pTable12->group[i].start_char_code) <= be::swap(pTable12->group[i-1].end_char_code))
-             return false;
-@@ -1161,17 +1163,17 @@ unsigned int CmapSubtable12NextCodepoint
-             *pRangeKey = nRange;
-         return 0x10FFFF;
-     }
- 
-     int iRange = (pRangeKey) ? *pRangeKey : 0;
-     // Just in case we have a bad key:
-     while (iRange > 0 && be::swap(pTable->group[iRange].start_char_code) > nUnicodePrev)
-         iRange--;
--    while (be::swap(pTable->group[iRange].end_char_code) < nUnicodePrev)
-+    while (iRange < nRange - 1 && be::swap(pTable->group[iRange].end_char_code) < nUnicodePrev)
-         iRange++;
- 
-     // Now iRange is the range containing nUnicodePrev.
- 
-     unsigned int nStartCode = be::swap(pTable->group[iRange].start_char_code);
-     unsigned int nEndCode = be::swap(pTable->group[iRange].end_char_code);
- 
-     if (nStartCode > nUnicodePrev)
-diff --git a/gfx/graphite2/src/call_machine.cpp b/gfx/graphite2/src/call_machine.cpp
---- a/gfx/graphite2/src/call_machine.cpp
-+++ b/gfx/graphite2/src/call_machine.cpp
-@@ -67,32 +67,34 @@ using namespace vm;
- struct regbank  {
-     slotref         is;
-     slotref *       map;
-     SlotMap       & smap;
-     slotref * const map_base;
-     const instr * & ip;
-     uint8           direction;
-     int8            flags;
-+    Machine::status_t & status;
- };
- 
- typedef bool        (* ip_t)(registers);
- 
- // Pull in the opcode definitions
- // We pull these into a private namespace so these otherwise common names dont
- // pollute the toplevel namespace.
- namespace {
- #define smap    reg.smap
- #define seg     smap.segment
- #define is      reg.is
- #define ip      reg.ip
- #define map     reg.map
- #define mapb    reg.map_base
- #define flags   reg.flags
- #define dir     reg.direction
-+#define status  reg.status
- 
- #include "inc/opcodes.h"
- 
- #undef smap
- #undef seg
- #undef is
- #undef ip
- #undef map
-@@ -108,17 +110,17 @@ Machine::stack_t  Machine::run(const ins
- {
-     assert(program != 0);
- 
-     // Declare virtual machine registers
-     const instr   * ip = program-1;
-     const byte    * dp = data;
-     stack_t       * sp = _stack + Machine::STACK_GUARD,
-             * const sb = sp;
--    regbank         reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0};
-+    regbank         reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0, _status};
- 
-     // Run the program        
-     while ((reinterpret_cast<ip_t>(*++ip))(dp, sp, sb, reg)) {}
-     const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
- 
-     check_final_stack(sp);
-     map = reg.map;
-     *map = reg.is;
-diff --git a/gfx/graphite2/src/direct_machine.cpp b/gfx/graphite2/src/direct_machine.cpp
---- a/gfx/graphite2/src/direct_machine.cpp
-+++ b/gfx/graphite2/src/direct_machine.cpp
-@@ -57,36 +57,37 @@ using namespace vm;
- namespace {
- 
- const void * direct_run(const bool          get_table_mode,
-                         const instr       * program,
-                         const byte        * data,
-                         Machine::stack_t  * stack,
-                         slotref         * & __map,
-                         uint8                _dir,
-+                        Machine::status_t & status,
-                         SlotMap           * __smap=0)
- {
-     // We need to define and return to opcode table from within this function 
-     // other inorder to take the addresses of the instruction bodies.
-     #include "inc/opcode_table.h"
-     if (get_table_mode)
-         return opcode_table;
- 
-     // Declare virtual machine registers
--    const instr       * ip = program;
--    const byte        * dp = data;
--    Machine::stack_t  * sp = stack + Machine::STACK_GUARD,
--                * const sb = sp;
--    SlotMap         & smap = *__smap;
--    Segment          & seg = smap.segment;
--    slotref             is = *__map,
--                     * map = __map,
--              * const mapb = smap.begin()+smap.context();
--    uint8            dir = _dir;
--    int8             flags = 0;
-+    const instr           * ip = program;
-+    const byte            * dp = data;
-+    Machine::stack_t      * sp = stack + Machine::STACK_GUARD,
-+                    * const sb = sp;
-+    SlotMap             & smap = *__smap;
-+    Segment              & seg = smap.segment;
-+    slotref                 is = *__map,
-+                         * map = __map,
-+                  * const mapb = smap.begin()+smap.context();
-+    uint8                  dir = _dir;
-+    int8                 flags = 0;
-     
-     // start the program
-     goto **ip;
- 
-     // Pull in the opcode definitions
-     #include "inc/opcodes.h"
-     
-     end:
-@@ -95,25 +96,26 @@ const void * direct_run(const bool      
-     return sp;
- }
- 
- }
- 
- const opcode_t * Machine::getOpcodeTable() throw()
- {
-     slotref * dummy;
--    return static_cast<const opcode_t *>(direct_run(true, 0, 0, 0, dummy, 0));
-+    Machine::status_t dumstat = Machine::finished;
-+    return static_cast<const opcode_t *>(direct_run(true, 0, 0, 0, dummy, 0, dumstat));
- }
- 
- 
- Machine::stack_t  Machine::run(const instr   * program,
-                                const byte    * data,
-                                slotref     * & is)
- {
-     assert(program != 0);
-     
-     const stack_t *sp = static_cast<const stack_t *>(
--                direct_run(false, program, data, _stack, is, _map.dir(), &_map));
-+                direct_run(false, program, data, _stack, is, _map.dir(), _status, &_map));
-     const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
-     check_final_stack(sp);
-     return ret;
- }
- 
-diff --git a/gfx/graphite2/src/inc/Code.h b/gfx/graphite2/src/inc/Code.h
---- a/gfx/graphite2/src/inc/Code.h
-+++ b/gfx/graphite2/src/inc/Code.h
-@@ -109,17 +109,17 @@ public:
-     int32 run(Machine &m, slotref * & map) const;
-     
-     CLASS_NEW_DELETE;
- };
- 
- inline
- size_t  Machine::Code::estimateCodeDataOut(size_t n_bc)
- {
--    return n_bc * (sizeof(instr)+sizeof(byte));
-+    return (n_bc + 1) * (sizeof(instr)+sizeof(byte));
- }
- 
- 
- inline Machine::Code::Code() throw()
- : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
-   _status(loaded), _constraint(false), _modify(false), _delete(false),
-   _own(false)
- {
-diff --git a/gfx/graphite2/src/inc/Machine.h b/gfx/graphite2/src/inc/Machine.h
---- a/gfx/graphite2/src/inc/Machine.h
-+++ b/gfx/graphite2/src/inc/Machine.h
-@@ -135,17 +135,18 @@ public:
- 
-     class Code;
- 
-     enum status_t {
-         finished = 0,
-         stack_underflow,
-         stack_not_empty,
-         stack_overflow,
--        slot_offset_out_bounds
-+        slot_offset_out_bounds,
-+        died_early
-     };
- 
-     Machine(SlotMap &) throw();
-     static const opcode_t *   getOpcodeTable() throw();
- 
-     CLASS_NEW_DELETE;
- 
-     SlotMap   & slotMap() const throw();
-diff --git a/gfx/graphite2/src/inc/TtfUtil.h b/gfx/graphite2/src/inc/TtfUtil.h
---- a/gfx/graphite2/src/inc/TtfUtil.h
-+++ b/gfx/graphite2/src/inc/TtfUtil.h
-@@ -132,21 +132,21 @@ public:
-     int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId,
-         int *nameIdList, int cNameIds, short *langIdList);
-     void SwapWString(void * pWStr, size_t nSize = 0); // throw (std::invalid_argument);
- #endif
- 
-     ////////////////////////////////// cmap lookup tools 
-     const void * FindCmapSubtable(const void * pCmap, int nPlatformId = 3, 
-         int nEncodingId = 1, size_t length = 0);
--    bool CheckCmapSubtable4(const void * pCmap31, size_t table_len /*, unsigned int maxgid*/);
-+    bool CheckCmapSubtable4(const void * pCmap31, const void * pCmapEnd /*, unsigned int maxgid*/);
-     gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey = 0);
-     unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId,
-         int * pRangeKey = 0);
--    bool CheckCmapSubtable12(const void *pCmap310, size_t table_len /*, unsigned int maxgid*/);
-+    bool CheckCmapSubtable12(const void *pCmap310, const void * pCmapEnd /*, unsigned int maxgid*/);
-     gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey = 0);
-     unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId,
-         int * pRangeKey = 0);
- 
-     ///////////////////////////////// horizontal metric data for a glyph
-     bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, 
-         const void * pHhea, int & nLsb, unsigned int & nAdvWid);
- 
-diff --git a/gfx/graphite2/src/inc/opcodes.h b/gfx/graphite2/src/inc/opcodes.h
---- a/gfx/graphite2/src/inc/opcodes.h
-+++ b/gfx/graphite2/src/inc/opcodes.h
-@@ -71,17 +71,17 @@ of the License or (at your option) any l
- #define use_params(n)       dp += n
- 
- #define declare_params(n)   const byte * param = dp; \
-                             use_params(n);
- 
- #define push(n)             { *++sp = n; }
- #define pop()               (*sp--)
- #define slotat(x)           (map[(x)])
--#define DIE                 { is=seg.last(); EXIT(1); }
-+#define DIE                 { is=seg.last(); status = Machine::died_early; EXIT(1); }
- #define POSITIONED          1
- 
- STARTOP(nop)
-     do {} while (0);
- ENDOP
- 
- STARTOP(push_byte)
-     declare_params(1);
-@@ -387,30 +387,30 @@ STARTOP(attr_set)
- ENDOP
- 
- STARTOP(attr_add)
-     declare_params(1);
-     const attrCode      slat = attrCode(uint8(*param));
-     const          int  val  = int(pop());
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
-         flags |= POSITIONED;
-     }
-     int res = is->getAttr(&seg, slat, 0);
-     is->setAttr(&seg, slat, 0, val + res, smap);
- ENDOP
- 
- STARTOP(attr_sub)
-     declare_params(1);
-     const attrCode      slat = attrCode(uint8(*param));
-     const          int  val  = int(pop());
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
-         flags |= POSITIONED;
-     }
-     int res = is->getAttr(&seg, slat, 0);
-     is->setAttr(&seg, slat, 0, res - val, smap);
- ENDOP
- 
- STARTOP(attr_set_slot)
-     declare_params(1);
-@@ -429,17 +429,17 @@ STARTOP(iattr_set_slot)
- ENDOP
- 
- STARTOP(push_slot_attr)
-     declare_params(2);
-     const attrCode      slat     = attrCode(uint8(param[0]));
-     const int           slot_ref = int8(param[1]);
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
-         flags |= POSITIONED;
-     }
-     slotref slot = slotat(slot_ref);
-     if (slot)
-     {
-         int res = slot->getAttr(&seg, slat, 0);
-         push(res);
-     }
-@@ -505,17 +505,17 @@ ENDOP
- 
- STARTOP(push_islot_attr)
-     declare_params(3);
-     const attrCode  slat     = attrCode(uint8(param[0]));
-     const int           slot_ref = int8(param[1]),
-                         idx      = uint8(param[2]);
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
-         flags |= POSITIONED;
-     }
-     slotref slot = slotat(slot_ref);
-     if (slot)
-     {
-         int res = slot->getAttr(&seg, slat, idx);
-         push(res);
-     }
-
diff --git a/gnu/packages/patches/icecat-update-graphite2.patch b/gnu/packages/patches/icecat-update-graphite2.patch
deleted file mode 100644
index af2c47bef7..0000000000
--- a/gnu/packages/patches/icecat-update-graphite2.patch
+++ /dev/null
@@ -1,9988 +0,0 @@
-Copied from upstream:
-https://hg.mozilla.org/releases/mozilla-esr38/raw-rev/ed4d2ce6046b
-
-# HG changeset patch
-# User Jonathan Kew <jkew@mozilla.com>
-# Date 1455126706 0
-# Node ID ed4d2ce6046b20287fd13c548dd3982fe1a24875
-# Parent  78d3632feb7b6f6046025352630bd4f5365f3106
-Bug 1246093 - Update graphite2 library to latest release on esr38. r=me,a=sledru+lizzard
-
-diff --git a/gfx/graphite2/COPYING b/gfx/graphite2/COPYING
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/COPYING
-@@ -0,0 +1,26 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2010, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+    Alternatively, you may use this library under the terms of the Mozilla
-+    Public License (http://mozilla.org/MPL) or under the GNU General Public
-+    License, as published by the Free Sofware Foundation; either version
-+    2 of the license or (at your option) any later version.
-+*/
-diff --git a/gfx/graphite2/LICENSE b/gfx/graphite2/LICENSE
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/LICENSE
-@@ -0,0 +1,510 @@
-+
-+                  GNU LESSER GENERAL PUBLIC LICENSE
-+                       Version 2.1, February 1999
-+
-+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-+	51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-+ Everyone is permitted to copy and distribute verbatim copies
-+ of this license document, but changing it is not allowed.
-+
-+[This is the first released version of the Lesser GPL.  It also counts
-+ as the successor of the GNU Library Public License, version 2, hence
-+ the version number 2.1.]
-+
-+                            Preamble
-+
-+  The licenses for most software are designed to take away your
-+freedom to share and change it.  By contrast, the GNU General Public
-+Licenses are intended to guarantee your freedom to share and change
-+free software--to make sure the software is free for all its users.
-+
-+  This license, the Lesser General Public License, applies to some
-+specially designated software packages--typically libraries--of the
-+Free Software Foundation and other authors who decide to use it.  You
-+can use it too, but we suggest you first think carefully about whether
-+this license or the ordinary General Public License is the better
-+strategy to use in any particular case, based on the explanations
-+below.
-+
-+  When we speak of free software, we are referring to freedom of use,
-+not price.  Our General Public Licenses are designed to make sure that
-+you have the freedom to distribute copies of free software (and charge
-+for this service if you wish); that you receive source code or can get
-+it if you want it; that you can change the software and use pieces of
-+it in new free programs; and that you are informed that you can do
-+these things.
-+
-+  To protect your rights, we need to make restrictions that forbid
-+distributors to deny you these rights or to ask you to surrender these
-+rights.  These restrictions translate to certain responsibilities for
-+you if you distribute copies of the library or if you modify it.
-+
-+  For example, if you distribute copies of the library, whether gratis
-+or for a fee, you must give the recipients all the rights that we gave
-+you.  You must make sure that they, too, receive or can get the source
-+code.  If you link other code with the library, you must provide
-+complete object files to the recipients, so that they can relink them
-+with the library after making changes to the library and recompiling
-+it.  And you must show them these terms so they know their rights.
-+
-+  We protect your rights with a two-step method: (1) we copyright the
-+library, and (2) we offer you this license, which gives you legal
-+permission to copy, distribute and/or modify the library.
-+
-+  To protect each distributor, we want to make it very clear that
-+there is no warranty for the free library.  Also, if the library is
-+modified by someone else and passed on, the recipients should know
-+that what they have is not the original version, so that the original
-+author's reputation will not be affected by problems that might be
-+introduced by others.
-+
-+  Finally, software patents pose a constant threat to the existence of
-+any free program.  We wish to make sure that a company cannot
-+effectively restrict the users of a free program by obtaining a
-+restrictive license from a patent holder.  Therefore, we insist that
-+any patent license obtained for a version of the library must be
-+consistent with the full freedom of use specified in this license.
-+
-+  Most GNU software, including some libraries, is covered by the
-+ordinary GNU General Public License.  This license, the GNU Lesser
-+General Public License, applies to certain designated libraries, and
-+is quite different from the ordinary General Public License.  We use
-+this license for certain libraries in order to permit linking those
-+libraries into non-free programs.
-+
-+  When a program is linked with a library, whether statically or using
-+a shared library, the combination of the two is legally speaking a
-+combined work, a derivative of the original library.  The ordinary
-+General Public License therefore permits such linking only if the
-+entire combination fits its criteria of freedom.  The Lesser General
-+Public License permits more lax criteria for linking other code with
-+the library.
-+
-+  We call this license the "Lesser" General Public License because it
-+does Less to protect the user's freedom than the ordinary General
-+Public License.  It also provides other free software developers Less
-+of an advantage over competing non-free programs.  These disadvantages
-+are the reason we use the ordinary General Public License for many
-+libraries.  However, the Lesser license provides advantages in certain
-+special circumstances.
-+
-+  For example, on rare occasions, there may be a special need to
-+encourage the widest possible use of a certain library, so that it
-+becomes a de-facto standard.  To achieve this, non-free programs must
-+be allowed to use the library.  A more frequent case is that a free
-+library does the same job as widely used non-free libraries.  In this
-+case, there is little to gain by limiting the free library to free
-+software only, so we use the Lesser General Public License.
-+
-+  In other cases, permission to use a particular library in non-free
-+programs enables a greater number of people to use a large body of
-+free software.  For example, permission to use the GNU C Library in
-+non-free programs enables many more people to use the whole GNU
-+operating system, as well as its variant, the GNU/Linux operating
-+system.
-+
-+  Although the Lesser General Public License is Less protective of the
-+users' freedom, it does ensure that the user of a program that is
-+linked with the Library has the freedom and the wherewithal to run
-+that program using a modified version of the Library.
-+
-+  The precise terms and conditions for copying, distribution and
-+modification follow.  Pay close attention to the difference between a
-+"work based on the library" and a "work that uses the library".  The
-+former contains code derived from the library, whereas the latter must
-+be combined with the library in order to run.
-+
-+                  GNU LESSER GENERAL PUBLIC LICENSE
-+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-+
-+  0. This License Agreement applies to any software library or other
-+program which contains a notice placed by the copyright holder or
-+other authorized party saying it may be distributed under the terms of
-+this Lesser General Public License (also called "this License").
-+Each licensee is addressed as "you".
-+
-+  A "library" means a collection of software functions and/or data
-+prepared so as to be conveniently linked with application programs
-+(which use some of those functions and data) to form executables.
-+
-+  The "Library", below, refers to any such software library or work
-+which has been distributed under these terms.  A "work based on the
-+Library" means either the Library or any derivative work under
-+copyright law: that is to say, a work containing the Library or a
-+portion of it, either verbatim or with modifications and/or translated
-+straightforwardly into another language.  (Hereinafter, translation is
-+included without limitation in the term "modification".)
-+
-+  "Source code" for a work means the preferred form of the work for
-+making modifications to it.  For a library, complete source code means
-+all the source code for all modules it contains, plus any associated
-+interface definition files, plus the scripts used to control
-+compilation and installation of the library.
-+
-+  Activities other than copying, distribution and modification are not
-+covered by this License; they are outside its scope.  The act of
-+running a program using the Library is not restricted, and output from
-+such a program is covered only if its contents constitute a work based
-+on the Library (independent of the use of the Library in a tool for
-+writing it).  Whether that is true depends on what the Library does
-+and what the program that uses the Library does.
-+
-+  1. You may copy and distribute verbatim copies of the Library's
-+complete source code as you receive it, in any medium, provided that
-+you conspicuously and appropriately publish on each copy an
-+appropriate copyright notice and disclaimer of warranty; keep intact
-+all the notices that refer to this License and to the absence of any
-+warranty; and distribute a copy of this License along with the
-+Library.
-+
-+  You may charge a fee for the physical act of transferring a copy,
-+and you may at your option offer warranty protection in exchange for a
-+fee.
-+
-+  2. You may modify your copy or copies of the Library or any portion
-+of it, thus forming a work based on the Library, and copy and
-+distribute such modifications or work under the terms of Section 1
-+above, provided that you also meet all of these conditions:
-+
-+    a) The modified work must itself be a software library.
-+
-+    b) You must cause the files modified to carry prominent notices
-+    stating that you changed the files and the date of any change.
-+
-+    c) You must cause the whole of the work to be licensed at no
-+    charge to all third parties under the terms of this License.
-+
-+    d) If a facility in the modified Library refers to a function or a
-+    table of data to be supplied by an application program that uses
-+    the facility, other than as an argument passed when the facility
-+    is invoked, then you must make a good faith effort to ensure that,
-+    in the event an application does not supply such function or
-+    table, the facility still operates, and performs whatever part of
-+    its purpose remains meaningful.
-+
-+    (For example, a function in a library to compute square roots has
-+    a purpose that is entirely well-defined independent of the
-+    application.  Therefore, Subsection 2d requires that any
-+    application-supplied function or table used by this function must
-+    be optional: if the application does not supply it, the square
-+    root function must still compute square roots.)
-+
-+These requirements apply to the modified work as a whole.  If
-+identifiable sections of that work are not derived from the Library,
-+and can be reasonably considered independent and separate works in
-+themselves, then this License, and its terms, do not apply to those
-+sections when you distribute them as separate works.  But when you
-+distribute the same sections as part of a whole which is a work based
-+on the Library, the distribution of the whole must be on the terms of
-+this License, whose permissions for other licensees extend to the
-+entire whole, and thus to each and every part regardless of who wrote
-+it.
-+
-+Thus, it is not the intent of this section to claim rights or contest
-+your rights to work written entirely by you; rather, the intent is to
-+exercise the right to control the distribution of derivative or
-+collective works based on the Library.
-+
-+In addition, mere aggregation of another work not based on the Library
-+with the Library (or with a work based on the Library) on a volume of
-+a storage or distribution medium does not bring the other work under
-+the scope of this License.
-+
-+  3. You may opt to apply the terms of the ordinary GNU General Public
-+License instead of this License to a given copy of the Library.  To do
-+this, you must alter all the notices that refer to this License, so
-+that they refer to the ordinary GNU General Public License, version 2,
-+instead of to this License.  (If a newer version than version 2 of the
-+ordinary GNU General Public License has appeared, then you can specify
-+that version instead if you wish.)  Do not make any other change in
-+these notices.
-+
-+  Once this change is made in a given copy, it is irreversible for
-+that copy, so the ordinary GNU General Public License applies to all
-+subsequent copies and derivative works made from that copy.
-+
-+  This option is useful when you wish to copy part of the code of
-+the Library into a program that is not a library.
-+
-+  4. You may copy and distribute the Library (or a portion or
-+derivative of it, under Section 2) in object code or executable form
-+under the terms of Sections 1 and 2 above provided that you accompany
-+it with the complete corresponding machine-readable source code, which
-+must be distributed under the terms of Sections 1 and 2 above on a
-+medium customarily used for software interchange.
-+
-+  If distribution of object code is made by offering access to copy
-+from a designated place, then offering equivalent access to copy the
-+source code from the same place satisfies the requirement to
-+distribute the source code, even though third parties are not
-+compelled to copy the source along with the object code.
-+
-+  5. A program that contains no derivative of any portion of the
-+Library, but is designed to work with the Library by being compiled or
-+linked with it, is called a "work that uses the Library".  Such a
-+work, in isolation, is not a derivative work of the Library, and
-+therefore falls outside the scope of this License.
-+
-+  However, linking a "work that uses the Library" with the Library
-+creates an executable that is a derivative of the Library (because it
-+contains portions of the Library), rather than a "work that uses the
-+library".  The executable is therefore covered by this License.
-+Section 6 states terms for distribution of such executables.
-+
-+  When a "work that uses the Library" uses material from a header file
-+that is part of the Library, the object code for the work may be a
-+derivative work of the Library even though the source code is not.
-+Whether this is true is especially significant if the work can be
-+linked without the Library, or if the work is itself a library.  The
-+threshold for this to be true is not precisely defined by law.
-+
-+  If such an object file uses only numerical parameters, data
-+structure layouts and accessors, and small macros and small inline
-+functions (ten lines or less in length), then the use of the object
-+file is unrestricted, regardless of whether it is legally a derivative
-+work.  (Executables containing this object code plus portions of the
-+Library will still fall under Section 6.)
-+
-+  Otherwise, if the work is a derivative of the Library, you may
-+distribute the object code for the work under the terms of Section 6.
-+Any executables containing that work also fall under Section 6,
-+whether or not they are linked directly with the Library itself.
-+
-+  6. As an exception to the Sections above, you may also combine or
-+link a "work that uses the Library" with the Library to produce a
-+work containing portions of the Library, and distribute that work
-+under terms of your choice, provided that the terms permit
-+modification of the work for the customer's own use and reverse
-+engineering for debugging such modifications.
-+
-+  You must give prominent notice with each copy of the work that the
-+Library is used in it and that the Library and its use are covered by
-+this License.  You must supply a copy of this License.  If the work
-+during execution displays copyright notices, you must include the
-+copyright notice for the Library among them, as well as a reference
-+directing the user to the copy of this License.  Also, you must do one
-+of these things:
-+
-+    a) Accompany the work with the complete corresponding
-+    machine-readable source code for the Library including whatever
-+    changes were used in the work (which must be distributed under
-+    Sections 1 and 2 above); and, if the work is an executable linked
-+    with the Library, with the complete machine-readable "work that
-+    uses the Library", as object code and/or source code, so that the
-+    user can modify the Library and then relink to produce a modified
-+    executable containing the modified Library.  (It is understood
-+    that the user who changes the contents of definitions files in the
-+    Library will not necessarily be able to recompile the application
-+    to use the modified definitions.)
-+
-+    b) Use a suitable shared library mechanism for linking with the
-+    Library.  A suitable mechanism is one that (1) uses at run time a
-+    copy of the library already present on the user's computer system,
-+    rather than copying library functions into the executable, and (2)
-+    will operate properly with a modified version of the library, if
-+    the user installs one, as long as the modified version is
-+    interface-compatible with the version that the work was made with.
-+
-+    c) Accompany the work with a written offer, valid for at least
-+    three years, to give the same user the materials specified in
-+    Subsection 6a, above, for a charge no more than the cost of
-+    performing this distribution.
-+
-+    d) If distribution of the work is made by offering access to copy
-+    from a designated place, offer equivalent access to copy the above
-+    specified materials from the same place.
-+
-+    e) Verify that the user has already received a copy of these
-+    materials or that you have already sent this user a copy.
-+
-+  For an executable, the required form of the "work that uses the
-+Library" must include any data and utility programs needed for
-+reproducing the executable from it.  However, as a special exception,
-+the materials to be distributed need not include anything that is
-+normally distributed (in either source or binary form) with the major
-+components (compiler, kernel, and so on) of the operating system on
-+which the executable runs, unless that component itself accompanies
-+the executable.
-+
-+  It may happen that this requirement contradicts the license
-+restrictions of other proprietary libraries that do not normally
-+accompany the operating system.  Such a contradiction means you cannot
-+use both them and the Library together in an executable that you
-+distribute.
-+
-+  7. You may place library facilities that are a work based on the
-+Library side-by-side in a single library together with other library
-+facilities not covered by this License, and distribute such a combined
-+library, provided that the separate distribution of the work based on
-+the Library and of the other library facilities is otherwise
-+permitted, and provided that you do these two things:
-+
-+    a) Accompany the combined library with a copy of the same work
-+    based on the Library, uncombined with any other library
-+    facilities.  This must be distributed under the terms of the
-+    Sections above.
-+
-+    b) Give prominent notice with the combined library of the fact
-+    that part of it is a work based on the Library, and explaining
-+    where to find the accompanying uncombined form of the same work.
-+
-+  8. You may not copy, modify, sublicense, link with, or distribute
-+the Library except as expressly provided under this License.  Any
-+attempt otherwise to copy, modify, sublicense, link with, or
-+distribute the Library is void, and will automatically terminate your
-+rights under this License.  However, parties who have received copies,
-+or rights, from you under this License will not have their licenses
-+terminated so long as such parties remain in full compliance.
-+
-+  9. You are not required to accept this License, since you have not
-+signed it.  However, nothing else grants you permission to modify or
-+distribute the Library or its derivative works.  These actions are
-+prohibited by law if you do not accept this License.  Therefore, by
-+modifying or distributing the Library (or any work based on the
-+Library), you indicate your acceptance of this License to do so, and
-+all its terms and conditions for copying, distributing or modifying
-+the Library or works based on it.
-+
-+  10. Each time you redistribute the Library (or any work based on the
-+Library), the recipient automatically receives a license from the
-+original licensor to copy, distribute, link with or modify the Library
-+subject to these terms and conditions.  You may not impose any further
-+restrictions on the recipients' exercise of the rights granted herein.
-+You are not responsible for enforcing compliance by third parties with
-+this License.
-+
-+  11. If, as a consequence of a court judgment or allegation of patent
-+infringement or for any other reason (not limited to patent issues),
-+conditions are imposed on you (whether by court order, agreement or
-+otherwise) that contradict the conditions of this License, they do not
-+excuse you from the conditions of this License.  If you cannot
-+distribute so as to satisfy simultaneously your obligations under this
-+License and any other pertinent obligations, then as a consequence you
-+may not distribute the Library at all.  For example, if a patent
-+license would not permit royalty-free redistribution of the Library by
-+all those who receive copies directly or indirectly through you, then
-+the only way you could satisfy both it and this License would be to
-+refrain entirely from distribution of the Library.
-+
-+If any portion of this section is held invalid or unenforceable under
-+any particular circumstance, the balance of the section is intended to
-+apply, and the section as a whole is intended to apply in other
-+circumstances.
-+
-+It is not the purpose of this section to induce you to infringe any
-+patents or other property right claims or to contest validity of any
-+such claims; this section has the sole purpose of protecting the
-+integrity of the free software distribution system which is
-+implemented by public license practices.  Many people have made
-+generous contributions to the wide range of software distributed
-+through that system in reliance on consistent application of that
-+system; it is up to the author/donor to decide if he or she is willing
-+to distribute software through any other system and a licensee cannot
-+impose that choice.
-+
-+This section is intended to make thoroughly clear what is believed to
-+be a consequence of the rest of this License.
-+
-+  12. If the distribution and/or use of the Library is restricted in
-+certain countries either by patents or by copyrighted interfaces, the
-+original copyright holder who places the Library under this License
-+may add an explicit geographical distribution limitation excluding those
-+countries, so that distribution is permitted only in or among
-+countries not thus excluded.  In such case, this License incorporates
-+the limitation as if written in the body of this License.
-+
-+  13. The Free Software Foundation may publish revised and/or new
-+versions of the Lesser General Public License from time to time.
-+Such new versions will be similar in spirit to the present version,
-+but may differ in detail to address new problems or concerns.
-+
-+Each version is given a distinguishing version number.  If the Library
-+specifies a version number of this License which applies to it and
-+"any later version", you have the option of following the terms and
-+conditions either of that version or of any later version published by
-+the Free Software Foundation.  If the Library does not specify a
-+license version number, you may choose any version ever published by
-+the Free Software Foundation.
-+
-+  14. If you wish to incorporate parts of the Library into other free
-+programs whose distribution conditions are incompatible with these,
-+write to the author to ask for permission.  For software which is
-+copyrighted by the Free Software Foundation, write to the Free
-+Software Foundation; we sometimes make exceptions for this.  Our
-+decision will be guided by the two goals of preserving the free status
-+of all derivatives of our free software and of promoting the sharing
-+and reuse of software generally.
-+
-+                            NO WARRANTY
-+
-+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-+
-+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+DAMAGES.
-+
-+                     END OF TERMS AND CONDITIONS
-+
-+           How to Apply These Terms to Your New Libraries
-+
-+  If you develop a new library, and you want it to be of the greatest
-+possible use to the public, we recommend making it free software that
-+everyone can redistribute and change.  You can do so by permitting
-+redistribution under these terms (or, alternatively, under the terms
-+of the ordinary General Public License).
-+
-+  To apply these terms, attach the following notices to the library.
-+It is safest to attach them to the start of each source file to most
-+effectively convey the exclusion of warranty; and each file should
-+have at least the "copyright" line and a pointer to where the full
-+notice is found.
-+
-+
-+    <one line to give the library's name and a brief idea of what it does.>
-+    Copyright (C) <year>  <name of author>
-+
-+    This library is free software; you can redistribute it and/or
-+    modify it under the terms of the GNU Lesser General Public
-+    License as published by the Free Software Foundation; either
-+    version 2.1 of the License, or (at your option) any later version.
-+
-+    This library 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
-+    Lesser General Public License for more details.
-+
-+    You should have received a copy of the GNU Lesser General Public
-+    License along with this library; if not, write to the Free Software
-+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-+
-+Also add information on how to contact you by electronic and paper mail.
-+
-+You should also get your employer (if you work as a programmer) or
-+your school, if any, to sign a "copyright disclaimer" for the library,
-+if necessary.  Here is a sample; alter the names:
-+
-+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-+  library `Frob' (a library for tweaking knobs) written by James
-+  Random Hacker.
-+
-+  <signature of Ty Coon>, 1 April 1990
-+  Ty Coon, President of Vice
-+
-+That's all there is to it!
-+
-+
-diff --git a/gfx/graphite2/README.md b/gfx/graphite2/README.md
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/README.md
-@@ -0,0 +1,32 @@
-+# Graphite engine
-+
-+## What is Graphite?
-+
-+Graphite is a system that can be used to create “smart fonts” capable of displaying writing systems with various complex behaviors. A smart font contains not only letter shapes but also additional instructions indicating how to combine and position the letters in complex ways.
-+
-+Graphite was primarily developed to provide the flexibility needed for minority languages which often need to be written according to slightly different rules than well-known languages that use the same script.
-+
-+Examples of complex script behaviors Graphite can handle include:
-+
-+* contextual shaping
-+* ligatures
-+* reordering
-+* split glyphs
-+* bidirectionality
-+* stacking diacritics
-+* complex positioning
-+* shape aware kerning
-+* automatic diacritic collision avoidance
-+
-+See [examples of scripts with complex rendering](http://scripts.sil.org/CmplxRndExamples).
-+
-+## Graphite system overview
-+The Graphite system consists of:
-+
-+* A rule-based programming language [Graphite Description Language](http://scripts.sil.org/cms/scripts/page.php?site_id=projects&item_id=graphite_devFont#gdl) (GDL) that can be used to describe the behavior of a writing system
-+* A compiler for that language
-+* A rendering engine that can serve as the layout component of a text-processing application
-+
-+Graphite renders TrueType fonts that have been extended by means of compiling a GDL program.
-+
-+Further technical information is available on the [Graphite technical overview](http://scripts.sil.org/cms/scripts/page.php?site_id=projects&item_id=graphite_techAbout) page.
-diff --git a/gfx/graphite2/README.mozilla b/gfx/graphite2/README.mozilla
---- a/gfx/graphite2/README.mozilla
-+++ b/gfx/graphite2/README.mozilla
-@@ -1,6 +1,7 @@
--This directory contains the Graphite2 library from http://hg.palaso.org/graphitedev
--
--Current version derived from upstream changeset 1efd96aeade9
--
-+This directory contains the Graphite2 library release 1.3.5 from
-+https://github.com/silnrsi/graphite/releases/download/1.3.5/graphite2-minimal-1.3.5.tgz
- See gfx/graphite2/moz-gr-update.sh for update procedure.
- 
-+Also includes two post-1.3.5 fixes:
-+a8b3ac2aed0eb132cd80efe7de88f8153e73c829
-+e569e28d83491fedb31b9220493f3c07f6ec6d80
-diff --git a/gfx/graphite2/include/graphite2/Font.h b/gfx/graphite2/include/graphite2/Font.h
---- a/gfx/graphite2/include/graphite2/Font.h
-+++ b/gfx/graphite2/include/graphite2/Font.h
-@@ -24,18 +24,18 @@
-     General Public License, as published by the Free Software Foundation,
-     either version 2 of the License or (at your option) any later version.
- */
- #pragma once
- 
- #include "graphite2/Types.h"
- 
- #define GR2_VERSION_MAJOR   1
--#define GR2_VERSION_MINOR   2
--#define GR2_VERSION_BUGFIX  4
-+#define GR2_VERSION_MINOR   3
-+#define GR2_VERSION_BUGFIX  5
- 
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- 
- typedef struct gr_face          gr_face;
- typedef struct gr_font          gr_font;
-diff --git a/gfx/graphite2/include/graphite2/Segment.h b/gfx/graphite2/include/graphite2/Segment.h
---- a/gfx/graphite2/include/graphite2/Segment.h
-+++ b/gfx/graphite2/include/graphite2/Segment.h
-@@ -115,35 +115,68 @@ enum gr_attrCode {
-     gr_slatJStretch,        
-     /// Amount this slot can shrink (not implemented)
-     gr_slatJShrink,         
-     /// Granularity by which this slot can stretch or shrink (not implemented)
-     gr_slatJStep,           
-     /// Justification weight for this glyph (not implemented)
-     gr_slatJWeight,         
-     /// Amount this slot mush shrink or stretch in design units
--    gr_slatJWidth,          
-+    gr_slatJWidth = 29,
-     /// SubSegment split point
-     gr_slatSegSplit = gr_slatJStretch + 29,
-     /// User defined attribute, see subattr for user attr number
-     gr_slatUserDefn,
-     /// Bidi level
--    gr_slatBidiLevel,
-+    gr_slatBidiLevel = 56,
-+    /// Collision flags
-+    gr_slatColFlags,
-+    /// Collision constraint rectangle left (bl.x)
-+    gr_slatColLimitblx,
-+    /// Collision constraint rectangle lower (bl.y)
-+    gr_slatColLimitbly,
-+    /// Collision constraint rectangle right (tr.x)
-+    gr_slatColLimittrx,
-+    /// Collision constraint rectangle upper (tr.y)
-+    gr_slatColLimittry,
-+    /// Collision shift x
-+    gr_slatColShiftx,
-+    /// Collision shift y
-+    gr_slatColShifty,
-+    /// Collision margin
-+    gr_slatColMargin,
-+    /// Margin cost weight
-+    gr_slatColMarginWt,
-+    // Additional glyph that excludes movement near this one:
-+    gr_slatColExclGlyph,
-+    gr_slatColExclOffx,
-+    gr_slatColExclOffy,
-+    // Collision sequence enforcing attributes:
-+    gr_slatSeqClass,
-+    gr_slatSeqProxClass,
-+    gr_slatSeqOrder,
-+    gr_slatSeqAboveXoff,
-+    gr_slatSeqAboveWt,
-+    gr_slatSeqBelowXlim,
-+    gr_slatSeqBelowWt,
-+    gr_slatSeqValignHt,
-+    gr_slatSeqValignWt,
-                             
-     /// not implemented
-     gr_slatMax,             
-     /// not implemented
-     gr_slatNoEffect = gr_slatMax + 1    
- };
- 
- enum gr_bidirtl {
-     /// Underlying paragraph direction is RTL
-     gr_rtl = 1,
-     /// Set this to not run the bidi pass internally, even if the font asks for it.
--    /// This presumes that the segment is in a single direction.
-+    /// This presumes that the segment is in a single direction. Most of the time
-+    /// this bit should be set unless you know you are passing full paragraphs of text.
-     gr_nobidi = 2,
-     /// Disable auto mirroring for rtl text
-     gr_nomirror = 4
- };
- 
- typedef struct gr_char_info     gr_char_info;
- typedef struct gr_segment       gr_segment;
- typedef struct gr_slot          gr_slot;
-diff --git a/gfx/graphite2/include/graphite2/Types.h b/gfx/graphite2/include/graphite2/Types.h
---- a/gfx/graphite2/include/graphite2/Types.h
-+++ b/gfx/graphite2/include/graphite2/Types.h
-@@ -53,17 +53,20 @@ enum gr_encform {
-   #else
-     #if defined __GNUC__
-       #define GR2_API    __attribute__((dllimport))
-     #else
-       #define GR2_API    __declspec(dllimport)
-     #endif
-   #endif
-   #define GR2_LOCAL
-+#elif __GNUC__ >= 4
-+  #if defined GRAPHITE2_STATIC
-+    #define GR2_API      __attribute__ ((visibility("hidden")))
-+  #else
-+    #define GR2_API      __attribute__ ((visibility("default")))
-+  #endif
-+  #define GR2_LOCAL      __attribute__ ((visibility("hidden")))
- #else
--  #if __GNUC__ >= 4
--    #define GR2_API      __attribute__ ((visibility("default")))
--    #define GR2_LOCAL       __attribute__ ((visibility("hidden")))
--  #else
--    #define GR2_API
--    #define GR2_LOCAL
--  #endif
-+  #define GR2_API
-+  #define GR2_LOCAL
- #endif
-+
-diff --git a/gfx/graphite2/moz-gr-update.sh b/gfx/graphite2/moz-gr-update.sh
---- a/gfx/graphite2/moz-gr-update.sh
-+++ b/gfx/graphite2/moz-gr-update.sh
-@@ -1,35 +1,49 @@
- #!/bin/bash
- 
- # Script used to update the Graphite2 library in the mozilla source tree
- 
- # This script lives in gfx/graphite2, along with the library source,
- # but must be run from the top level of the mozilla-central tree.
- 
--# It expects to find a checkout of the graphite2 tree in a directory "graphitedev"
--# alongside the current mozilla tree that is to be updated.
--# Expect error messages from the copy commands if this is not found!
-+# Run as
-+#
-+#    ./gfx/graphite2/moz-gr-update.sh RELEASE
-+#
-+# where RELEASE is the graphite2 release to be used, e.g. "1.3.4".
- 
--# copy the source and headers
--cp -R ../graphitedev/src/* gfx/graphite2/src
--cp ../graphitedev/include/graphite2/* gfx/graphite2/include/graphite2
-+RELEASE=$1
- 
--# record the upstream changeset that was used
--CHANGESET=$(cd ../graphitedev/ && hg log | head -n 1 | cut -d : -f 1,3 | sed -e 's/:/ /')
--echo "This directory contains the Graphite2 library from http://hg.palaso.org/graphitedev\n" > gfx/graphite2/README.mozilla
--echo "Current version derived from upstream" $CHANGESET >> gfx/graphite2/README.mozilla
--echo "\nSee" $0 "for update procedure.\n" >> gfx/graphite2/README.mozilla
-+if [ "x$RELEASE" == "x" ]
-+then
-+    echo "Must provide the version number to be used."
-+    exit 1
-+fi
-+
-+TARBALL="https://github.com/silnrsi/graphite/releases/download/$RELEASE/graphite2-minimal-$RELEASE.tgz"
-+
-+foo=`basename $0`
-+TMPFILE=`mktemp -t ${foo}` || exit 1
-+
-+curl -L "$TARBALL" -o "$TMPFILE"
-+tar -x -z -C gfx/graphite2/ --strip-components 1 -f "$TMPFILE" || exit 1
-+rm "$TMPFILE"
-+
-+echo "This directory contains the Graphite2 library release $RELEASE from" > gfx/graphite2/README.mozilla
-+echo "$TARBALL" >> gfx/graphite2/README.mozilla
-+echo ""
-+echo "See" $0 "for update procedure." >> gfx/graphite2/README.mozilla
- 
- # fix up includes because of bug 721839 (cstdio) and bug 803066 (Windows.h)
--find gfx/graphite2/ -name "*.cpp" -exec perl -p -i -e "s/<cstdio>/<stdio.h>/;s/Windows.h/windows.h/;" {} \;
--find gfx/graphite2/ -name "*.h" -exec perl -p -i -e "s/<cstdio>/<stdio.h>/;s/Windows.h/windows.h/;" {} \;
-+#find gfx/graphite2/ -name "*.cpp" -exec perl -p -i -e "s/<cstdio>/<stdio.h>/;s/Windows.h/windows.h/;" {} \;
-+#find gfx/graphite2/ -name "*.h" -exec perl -p -i -e "s/<cstdio>/<stdio.h>/;s/Windows.h/windows.h/;" {} \;
- 
- # summarize what's been touched
--echo Updated to $CHANGESET.
-+echo Updated to $RELEASE.
- echo Here is what changed in the gfx/graphite2 directory:
- echo
- 
- hg stat gfx/graphite2
- 
- echo
- echo If gfx/graphite2/src/files.mk has changed, please make corresponding
- echo changes to gfx/graphite2/src/moz.build
-diff --git a/gfx/graphite2/src/CMakeLists.txt b/gfx/graphite2/src/CMakeLists.txt
---- a/gfx/graphite2/src/CMakeLists.txt
-+++ b/gfx/graphite2/src/CMakeLists.txt
-@@ -69,29 +69,31 @@ add_library(graphite2 SHARED
-     ${GRAPHITE2_VM_TYPE}_machine.cpp
-     gr_char_info.cpp
-     gr_features.cpp
-     gr_face.cpp
-     gr_font.cpp
-     gr_logging.cpp
-     gr_segment.cpp
-     gr_slot.cpp
--    Bidi.cpp
-     CachedFace.cpp
-     CmapCache.cpp
-     Code.cpp
-+    Collider.cpp
-+    Decompressor.cpp
-     Face.cpp
-     FeatureMap.cpp
-     Font.cpp
-     GlyphFace.cpp
-     GlyphCache.cpp
-+    Intervals.cpp
-     Justifier.cpp
-     NameTable.cpp
-     Pass.cpp
--    Rule.cpp
-+    Position.cpp
-     Segment.cpp
-     Silf.cpp
-     Slot.cpp
-     Sparse.cpp
-     TtfUtil.cpp
-     UtfCodec.cpp
-     ${FILEFACE}
-     ${SEGCACHE}
-@@ -99,27 +101,28 @@ add_library(graphite2 SHARED
- 
- set_target_properties(graphite2 PROPERTIES  PUBLIC_HEADER "${GRAPHITE_HEADERS}"
-                                             SOVERSION ${GRAPHITE_SO_VERSION}
-                                             VERSION ${GRAPHITE_VERSION}
-                                             LT_VERSION_CURRENT ${GRAPHITE_API_CURRENT}
-                                             LT_VERSION_REVISION ${GRAPHITE_API_REVISION}
-                                             LT_VERSION_AGE ${GRAPHITE_API_AGE})
- 
--if (${CMAKE_BUILD_TYPE} STREQUAL "ClangASN")
--    set(GRAPHITE_LINK_FLAGS "-fsanitize=address")
--else (${CMAKE_BUILD_TYPE} STREQUAL "ClangASN")
--    set(GRAPHITE_LINK_FLAGS "")
--endif (${CMAKE_BUILD_TYPE} STREQUAL "ClangASN")
--
- if  (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
-     set_target_properties(graphite2 PROPERTIES 
-         COMPILE_FLAGS   "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wctor-dtor-privacy -Wnon-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector"
-         LINK_FLAGS      "-nodefaultlibs ${GRAPHITE_LINK_FLAGS}" 
-         LINKER_LANGUAGE C)
-+    if (CMAKE_COMPILER_IS_GNUCXX)
-+        add_definitions(-Wdouble-promotion)
-+    endif (CMAKE_COMPILER_IS_GNUCXX)
-+    message(STATUS "Compiler ID is: ${CMAKE_CXX_COMPILER_ID}")
-+    if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
-+        add_definitions(-Wimplicit-fallthrough)
-+    endif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
-     if (${CMAKE_CXX_COMPILER} MATCHES  ".*mingw.*")
-         target_link_libraries(graphite2 kernel32 msvcr90 mingw32 gcc user32)
-     else (${CMAKE_CXX_COMPILER} MATCHES  ".*mingw.*")
-         if (GRAPHITE2_ASAN)
-             target_link_libraries(graphite2 c gcc_s)
-         else (GRAPHITE2_ASAN)
-             target_link_libraries(graphite2 c gcc)
-         endif (GRAPHITE2_ASAN)
-@@ -127,17 +130,17 @@ if  (${CMAKE_SYSTEM_NAME} STREQUAL "Linu
-         nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
-     endif (${CMAKE_CXX_COMPILER} MATCHES  ".*mingw.*")
-     set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
-     CREATE_LIBTOOL_FILE(graphite2 "/lib${LIB_SUFFIX}")
- endif (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
- 
- if  (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-     set_target_properties(graphite2 PROPERTIES 
--        COMPILE_FLAGS   "-Wall -Wextra -Wno-unknown-pragmas -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector"
-+        COMPILE_FLAGS   "-Wall -Wextra -Wno-unknown-pragmas -Wimplicit-fallthrough -Wendif-labels -Wshadow -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -fno-rtti -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-stack-protector"
-         LINK_FLAGS      "-nodefaultlibs" 
-         LINKER_LANGUAGE C)
-     target_link_libraries(graphite2 c)
-     include(Graphite)
-     nolib_test(stdc++ $<TARGET_SONAME_FILE:graphite2>)
-     set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
-     CREATE_LIBTOOL_FILE(graphite2 "/lib${LIB_SUFFIX}")
- endif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
-diff --git a/gfx/graphite2/src/CmapCache.cpp b/gfx/graphite2/src/CmapCache.cpp
---- a/gfx/graphite2/src/CmapCache.cpp
-+++ b/gfx/graphite2/src/CmapCache.cpp
-@@ -33,31 +33,31 @@ of the License or (at your option) any l
- 
- 
- using namespace graphite2;
- 
- const void * bmp_subtable(const Face::Table & cmap)
- {
-     const void * stbl;
-     if (!cmap.size()) return 0;
--    if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()))
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()))
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()))
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()))
--     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size())))
-+    if (TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 1, cmap.size()), cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 3, cmap.size()), cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 2, cmap.size()), cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 1, cmap.size()), cmap.size())
-+     || TtfUtil::CheckCmapSubtable4(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 0, cmap.size()), cmap.size()))
-         return stbl;
-     return 0;
- }
- 
- const void * smp_subtable(const Face::Table & cmap)
- {
-     const void * stbl;
-     if (!cmap.size()) return 0;
--    if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()))
--     || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size())))
-+    if (TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 3, 10, cmap.size()), cmap.size())
-+     || TtfUtil::CheckCmapSubtable12(stbl = TtfUtil::FindCmapSubtable(cmap, 0, 4, cmap.size()), cmap.size()))
-         return stbl;
-     return 0;
- }
- 
- template <unsigned int (*NextCodePoint)(const void *, unsigned int, int *),
-           uint16 (*LookupCodePoint)(const void *, unsigned int, int)>
- bool cache_subtable(uint16 * blocks[], const void * cst, const unsigned int limit)
- {
-diff --git a/gfx/graphite2/src/Code.cpp b/gfx/graphite2/src/Code.cpp
---- a/gfx/graphite2/src/Code.cpp
-+++ b/gfx/graphite2/src/Code.cpp
-@@ -37,17 +37,17 @@ of the License or (at your option) any l
- #include "inc/Code.h"
- #include "inc/Face.h"
- #include "inc/GlyphFace.h"
- #include "inc/GlyphCache.h"
- #include "inc/Machine.h"
- #include "inc/Rule.h"
- #include "inc/Silf.h"
- 
--#include <stdio.h>
-+#include <cstdio>
- 
- #ifdef NDEBUG
- #ifdef __GNUC__
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- #endif
- 
- 
-@@ -84,112 +84,119 @@ public:
-     struct limits;
-     struct analysis
-     {
-         uint8     slotref;
-         context   contexts[256];
-         byte      max_ref;
-         
-         analysis() : slotref(0), max_ref(0) {};
--        void set_ref(int index) throw();
-+        void set_ref(int index, bool incinsert=false) throw();
-+        void set_noref(int index) throw();
-         void set_changed(int index) throw();
- 
-     };
-     
--    decoder(const limits & lims, Code &code) throw();
-+    decoder(limits & lims, Code &code, enum passtype pt) throw();
-     
-     bool        load(const byte * bc_begin, const byte * bc_end);
-     void        apply_analysis(instr * const code, instr * code_end);
-     byte        max_ref() { return _analysis.max_ref; }
-     int         pre_context() const { return _pre_context; }
-     
- private:
-     opcode      fetch_opcode(const byte * bc);
-     void        analyse_opcode(const opcode, const int8 * const dp) throw();
-     bool        emit_opcode(opcode opc, const byte * & bc);
-     bool        validate_opcode(const opcode opc, const byte * const bc);
-     bool        valid_upto(const uint16 limit, const uint16 x) const throw();
-+    bool        test_context() const throw();
-     void        failure(const status_t s) const throw() { _code.failure(s); }
-     
-     Code              & _code;
-     int                 _pre_context;
-     uint16              _rule_length;
-     instr             * _instr;
-     byte              * _data;
--    const limits      & _max;
-+    limits            & _max;
-     analysis            _analysis;
-+    enum passtype       _passtype;
-+    int                 _stack_depth;
-+    bool                _in_ctxt_item;
- };
- 
- 
- struct Machine::Code::decoder::limits
- {
--  const byte * const bytecode;
-+  const byte       * bytecode;
-   const uint8        pre_context;
-   const uint16       rule_length,
-                      classes,
-                      glyf_attrs,
-                      features;
-   const byte         attrid[gr_slatMax];
- };
-    
--inline Machine::Code::decoder::decoder(const limits & lims, Code &code) throw()
-+inline Machine::Code::decoder::decoder(limits & lims, Code &code, enum passtype pt) throw()
- : _code(code),
-   _pre_context(code._constraint ? 0 : lims.pre_context), 
-   _rule_length(code._constraint ? 1 : lims.rule_length), 
--  _instr(code._code), _data(code._data), _max(lims)
-+  _instr(code._code), _data(code._data), _max(lims), _passtype(pt),
-+  _stack_depth(0),
-+  _in_ctxt_item(false)
- { }
-     
- 
- 
- Machine::Code::Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
--           uint8 pre_context, uint16 rule_length, const Silf & silf, const Face & face)
-+           uint8 pre_context, uint16 rule_length, const Silf & silf, const Face & face,
-+           enum passtype pt, byte * * const _out)
-  :  _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0), _status(loaded),
--    _constraint(is_constraint), _modify(false), _delete(false), _own(true)
-+    _constraint(is_constraint), _modify(false), _delete(false), _own(_out==0)
- {
- #ifdef GRAPHITE2_TELEMETRY
-     telemetry::category _code_cat(face.tele.code);
- #endif
-     assert(bytecode_begin != 0);
-     if (bytecode_begin == bytecode_end)
-     {
--      ::new (this) Code();
-+      // ::new (this) Code();
-       return;
-     }
-     assert(bytecode_end > bytecode_begin);
-     const opcode_t *    op_to_fn = Machine::getOpcodeTable();
-     
--    // Allocate code and dat target buffers, these sizes are a worst case 
-+    // Allocate code and data target buffers, these sizes are a worst case
-     // estimate.  Once we know their real sizes the we'll shrink them.
--    _code = static_cast<instr *>(malloc((bytecode_end - bytecode_begin)
--                                             * sizeof(instr)));
--    _data = static_cast<byte *>(malloc((bytecode_end - bytecode_begin)
--                                             * sizeof(byte)));
-+    if (_out)   _code = reinterpret_cast<instr *>(*_out);
-+    else        _code = static_cast<instr *>(malloc(estimateCodeDataOut(bytecode_end-bytecode_begin)));
-+    _data = reinterpret_cast<byte *>(_code + (bytecode_end - bytecode_begin));
-     
-     if (!_code || !_data) {
-         failure(alloc_failed);
-         return;
-     }
-     
--    const decoder::limits lims = {
-+    decoder::limits lims = {
-         bytecode_end,
-         pre_context,
-         rule_length,
-         silf.numClasses(),
-         face.glyphs().numAttrs(),
-         face.numFeatures(), 
-         {1,1,1,1,1,1,1,1, 
-          1,1,1,1,1,1,1,255,
-          1,1,1,1,1,1,1,1, 
-          1,1,1,1,1,1,0,0, 
-          0,0,0,0,0,0,0,0, 
-          0,0,0,0,0,0,0,0, 
-          0,0,0,0,0,0,0, silf.numUser()}
-     };
-     
--    decoder dec(lims, *this);
-+    decoder dec(lims, *this, pt);
-     if(!dec.load(bytecode_begin, bytecode_end))
-        return;
-     
-     // Is this an empty program?
-     if (_instr_count == 0)
-     {
-       release_buffers();
-       ::new (this) Code();
-@@ -204,20 +211,25 @@ Machine::Code::Code(bool is_constraint, 
- 
-     assert((_constraint && immutable()) || !_constraint);
-     dec.apply_analysis(_code, _code + _instr_count);
-     _max_ref = dec.max_ref();
-     
-     // Now we know exactly how much code and data the program really needs
-     // realloc the buffers to exactly the right size so we don't waste any 
-     // memory.
--    assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_instr_count));
--    assert((bytecode_end - bytecode_begin) >= std::ptrdiff_t(_data_size));
--    _code = static_cast<instr *>(realloc(_code, (_instr_count+1)*sizeof(instr)));
--    _data = static_cast<byte *>(realloc(_data, _data_size*sizeof(byte)));
-+    assert((bytecode_end - bytecode_begin) >= ptrdiff_t(_instr_count));
-+    assert((bytecode_end - bytecode_begin) >= ptrdiff_t(_data_size));
-+    memmove(_code + (_instr_count+1), _data, _data_size*sizeof(byte));
-+    size_t const total_sz = ((_instr_count+1) + (_data_size + sizeof(instr)-1)/sizeof(instr))*sizeof(instr);
-+    if (_out)
-+        *_out += total_sz;
-+    else
-+        _code = static_cast<instr *>(realloc(_code, total_sz));
-+   _data = reinterpret_cast<byte *>(_code + (_instr_count+1));
- 
-     if (!_code)
-     {
-         failure(alloc_failed);
-         return;
-     }
- 
-     // Make this RET_ZERO, we should never reach this but just in case ...
-@@ -232,16 +244,17 @@ Machine::Code::~Code() throw ()
- {
-     if (_own)
-         release_buffers();
- }
- 
- 
- bool Machine::Code::decoder::load(const byte * bc, const byte * bc_end)
- {
-+    _max.bytecode = bc_end;
-     while (bc < bc_end)
-     {
-         const opcode opc = fetch_opcode(bc++);
-         if (opc == vm::MAX_OPCODE)
-             return false;
-         
-         analyse_opcode(opc, reinterpret_cast<const int8 *>(bc));
-         
-@@ -261,141 +274,194 @@ opcode Machine::Code::decoder::fetch_opc
- 
-     // Do some basic sanity checks based on what we know about the opcode
-     if (!validate_opcode(opc, bc))  return MAX_OPCODE;
- 
-     // And check it's arguments as far as possible
-     switch (opc)
-     {
-         case NOP :
-+            break;
-         case PUSH_BYTE :
-         case PUSH_BYTEU :
-         case PUSH_SHORT :
-         case PUSH_SHORTU :
-         case PUSH_LONG :
-+            ++_stack_depth;
-+            break;
-         case ADD :
-         case SUB :
-         case MUL :
-         case DIV :
-         case MIN_ :
-         case MAX_ :
--        case NEG :
--        case TRUNC8 :
--        case TRUNC16 :
--        case COND :
-         case AND :
-         case OR :
--        case NOT :
-         case EQUAL :
-         case NOT_EQ :
-         case LESS :
-         case GTR :
-         case LESS_EQ :
-         case GTR_EQ :
-+        case BITOR :
-+        case BITAND :
-+            if (--_stack_depth <= 0)
-+                failure(underfull_stack);
-+            break;
-+        case NEG :
-+        case TRUNC8 :
-+        case TRUNC16 :
-+        case NOT :
-+        case BITNOT :
-+        case BITSET :
-+            if (_stack_depth <= 0)
-+                failure(underfull_stack);
-+            break;
-+        case COND :
-+            _stack_depth -= 2;
-+            if (_stack_depth <= 0)
-+                failure(underfull_stack);
-             break;
-         case NEXT :
-         case NEXT_N :           // runtime checked
-         case COPY_NEXT :
-+            test_context();
-             ++_pre_context;
-             break;
-         case PUT_GLYPH_8BIT_OBS :
-             valid_upto(_max.classes, bc[0]);
-+            test_context();
-             break;
-         case PUT_SUBS_8BIT_OBS :
-             valid_upto(_rule_length, _pre_context + int8(bc[0]));
-             valid_upto(_max.classes, bc[1]);
-             valid_upto(_max.classes, bc[2]);
-+            test_context();
-             break;
-         case PUT_COPY :
-             valid_upto(_rule_length, _pre_context + int8(bc[0]));
-+            test_context();
-             break;
-         case INSERT :
--            --_pre_context;
-+            if (_passtype >= PASS_TYPE_POSITIONING)
-+                failure(invalid_opcode);
-+            else
-+                --_pre_context;
-             break;
-         case DELETE :
-+            if (_passtype >= PASS_TYPE_POSITIONING)
-+                failure(invalid_opcode);
-+            test_context();
-             break;
-         case ASSOC :
-             for (uint8 num = bc[0]; num; --num)
-                 valid_upto(_rule_length, _pre_context + int8(bc[num]));
-+            test_context();
-             break;
-         case CNTXT_ITEM :
-             valid_upto(_max.rule_length, _max.pre_context + int8(bc[0]));
--            if (bc + 2 + bc[1] >= _max.bytecode)  failure(jump_past_end);
--            if (_pre_context != 0)                failure(nested_context_item);
-+            if (bc + 2 + bc[1] >= _max.bytecode)    failure(jump_past_end);
-+            if (_in_ctxt_item)                      failure(nested_context_item);
-             break;
-         case ATTR_SET :
-         case ATTR_ADD :
-         case ATTR_SUB :
-         case ATTR_SET_SLOT :
-+            if (--_stack_depth < 0)
-+                failure(underfull_stack);
-             valid_upto(gr_slatMax, bc[0]);
-+            test_context();
-             break;
-         case IATTR_SET_SLOT :
-+            if (--_stack_depth < 0)
-+                failure(underfull_stack);
-             if (valid_upto(gr_slatMax, bc[0]))
-                 valid_upto(_max.attrid[bc[0]], bc[1]);
-+            test_context();
-             break;
-         case PUSH_SLOT_ATTR :
-+            ++_stack_depth;
-             valid_upto(gr_slatMax, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-             break;
-         case PUSH_GLYPH_ATTR_OBS :
-+            ++_stack_depth;
-             valid_upto(_max.glyf_attrs, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-             break;
-         case PUSH_GLYPH_METRIC :
-+            ++_stack_depth;
-             valid_upto(kgmetDescent, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-             // level: dp[2] no check necessary
-             break;
-         case PUSH_FEAT :
-+            ++_stack_depth;
-             valid_upto(_max.features, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-             break;
-         case PUSH_ATT_TO_GATTR_OBS :
-+            ++_stack_depth;
-             valid_upto(_max.glyf_attrs, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-             break;
-         case PUSH_ATT_TO_GLYPH_METRIC :
-+            ++_stack_depth;
-             valid_upto(kgmetDescent, bc[0]);
-             valid_upto(_rule_length, _pre_context + int8(bc[1]));
-             // level: dp[2] no check necessary
-             break;
-         case PUSH_ISLOT_ATTR :
-+            ++_stack_depth;
-             if (valid_upto(gr_slatMax, bc[0]))
-             {
-                 valid_upto(_rule_length, _pre_context + int8(bc[1]));
-                 valid_upto(_max.attrid[bc[0]], bc[2]);
-             }
-             break;
-         case PUSH_IGLYPH_ATTR :// not implemented
-+            ++_stack_depth;
-+            break;
-         case POP_RET :
-+            if (--_stack_depth < 0)
-+                failure(underfull_stack);
-+            GR_FALLTHROUGH;
-+            // no break
-         case RET_ZERO :
-         case RET_TRUE :
-             break;
-         case IATTR_SET :
-         case IATTR_ADD :
-         case IATTR_SUB :
-+            if (--_stack_depth < 0)
-+                failure(underfull_stack);
-             if (valid_upto(gr_slatMax, bc[0]))
-                 valid_upto(_max.attrid[bc[0]], bc[1]);
-+            test_context();
-             break;
-         case PUSH_PROC_STATE :  // dummy: dp[0] no check necessary
-         case PUSH_VERSION :
-+            ++_stack_depth;
-             break;
-         case PUT_SUBS :
-             valid_upto(_rule_length, _pre_context + int8(bc[0]));
-             valid_upto(_max.classes, uint16(bc[1]<< 8) | bc[2]);
-             valid_upto(_max.classes, uint16(bc[3]<< 8) | bc[4]);
-+            test_context();
-             break;
-         case PUT_SUBS2 :        // not implemented
-         case PUT_SUBS3 :        // not implemented
-             break;
-         case PUT_GLYPH :
-             valid_upto(_max.classes, uint16(bc[0]<< 8) | bc[1]);
-+            test_context();
-             break;
-         case PUSH_GLYPH_ATTR :
-         case PUSH_ATT_TO_GLYPH_ATTR :
-+            ++_stack_depth;
-             valid_upto(_max.glyf_attrs, uint16(bc[0]<< 8) | bc[1]);
-             valid_upto(_rule_length, _pre_context + int8(bc[2]));
-             break;
-         default:
-             failure(invalid_opcode);
-             break;
-     }
- 
-@@ -410,62 +476,77 @@ void Machine::Code::decoder::analyse_opc
-   switch (opc)
-   {
-     case DELETE :
-       _code._delete = true;
-       break;
-     case PUT_GLYPH_8BIT_OBS :
-     case PUT_GLYPH :
-       _code._modify = true;
--      _analysis.set_changed(_analysis.slotref);
-+      _analysis.set_changed(0);
-+      break;
-+    case ATTR_SET :
-+    case ATTR_ADD :
-+    case ATTR_SET_SLOT :
-+    case IATTR_SET_SLOT :
-+    case IATTR_SET :
-+    case IATTR_ADD :
-+    case IATTR_SUB :
-+      _analysis.set_noref(0);
-       break;
-     case NEXT :
-     case COPY_NEXT :
-       if (!_analysis.contexts[_analysis.slotref].flags.inserted)
-         ++_analysis.slotref;
-       _analysis.contexts[_analysis.slotref] = context(_code._instr_count+1);
--      if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref;
-+      // if (_analysis.slotref > _analysis.max_ref) _analysis.max_ref = _analysis.slotref;
-       break;
-     case INSERT :
-       _analysis.contexts[_analysis.slotref].flags.inserted = true;
-       _code._modify = true;
-       break;
-     case PUT_SUBS_8BIT_OBS :    // slotref on 1st parameter
-     case PUT_SUBS : 
-       _code._modify = true;
--      _analysis.set_changed(_analysis.slotref);
-+      _analysis.set_changed(0);
-+      GR_FALLTHROUGH;
-       // no break
-     case PUT_COPY :
-     {
--      if (arg[0] != 0) { _analysis.set_changed(_analysis.slotref); _code._modify = true; }
-+      if (arg[0] != 0) { _analysis.set_changed(0); _code._modify = true; }
-       if (arg[0] <= 0 && -arg[0] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
--        _analysis.set_ref(_analysis.slotref + arg[0] - _analysis.contexts[_analysis.slotref].flags.inserted);
--      else if (_analysis.slotref + arg[0] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[0];
-+        _analysis.set_ref(arg[0], true);
-+      else if (arg[0] > 0)
-+        _analysis.set_ref(arg[0], true);
-       break;
-     }
-     case PUSH_ATT_TO_GATTR_OBS : // slotref on 2nd parameter
-         if (_code._constraint) return;
-+        GR_FALLTHROUGH;
-         // no break
-     case PUSH_GLYPH_ATTR_OBS :
-     case PUSH_SLOT_ATTR :
-     case PUSH_GLYPH_METRIC :
-     case PUSH_ATT_TO_GLYPH_METRIC :
-     case PUSH_ISLOT_ATTR :
-     case PUSH_FEAT :
-       if (arg[1] <= 0 && -arg[1] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
--        _analysis.set_ref(_analysis.slotref + arg[1] - _analysis.contexts[_analysis.slotref].flags.inserted);
--      else if (_analysis.slotref + arg[1] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[1];
-+        _analysis.set_ref(arg[1], true);
-+      else if (arg[1] > 0)
-+        _analysis.set_ref(arg[1], true);
-       break;
-     case PUSH_ATT_TO_GLYPH_ATTR :
-         if (_code._constraint) return;
-+        GR_FALLTHROUGH;
-         // no break
-     case PUSH_GLYPH_ATTR :
-       if (arg[2] <= 0 && -arg[2] <= _analysis.slotref - _analysis.contexts[_analysis.slotref].flags.inserted)
--        _analysis.set_ref(_analysis.slotref + arg[2] - _analysis.contexts[_analysis.slotref].flags.inserted);
--      else if (_analysis.slotref + arg[2] > _analysis.max_ref) _analysis.max_ref = _analysis.slotref + arg[2];
-+        _analysis.set_ref(arg[2], true);
-+      else if (arg[2] > 0)
-+        _analysis.set_ref(arg[2], true);
-       break;
-     case ASSOC :                // slotrefs in varargs
-       break;
-     default:
-         break;
-   }
- }
- 
-@@ -494,32 +575,41 @@ bool Machine::Code::decoder::emit_opcode
-         _code._data_size += param_sz;
-     }
-     
-     // recursively decode a context item so we can split the skip into 
-     // instruction and data portions.
-     if (opc == CNTXT_ITEM)
-     {
-         assert(_pre_context == 0);
-+        _in_ctxt_item = true;
-         _pre_context = _max.pre_context + int8(_data[-2]);
-         _rule_length = _max.rule_length;
- 
-         const size_t ctxt_start = _code._instr_count;
-         byte & instr_skip = _data[-1];
-         byte & data_skip  = *_data++;
-         ++_code._data_size;
-+        const byte *curr_end = _max.bytecode;
- 
-         if (load(bc, bc + instr_skip))
-         {
-             bc += instr_skip;
-             data_skip  = instr_skip - (_code._instr_count - ctxt_start);
-             instr_skip = _code._instr_count - ctxt_start;
-+            _max.bytecode = curr_end;
- 
-             _rule_length = 1;
-             _pre_context = 0;
-+            _in_ctxt_item = false;
-+        }
-+        else
-+        {
-+            _pre_context = 0;
-+            return false;
-         }
-     }
-     
-     return bool(_code);
- }
- 
- 
- void Machine::Code::decoder::apply_analysis(instr * const code, instr * code_end)
-@@ -533,87 +623,115 @@ void Machine::Code::decoder::apply_analy
-     {
-         if (!c->flags.referenced || !c->flags.changed) continue;
-         
-         instr * const tip = code + c->codeRef + tempcount;        
-         memmove(tip+1, tip, (code_end - tip) * sizeof(instr));
-         *tip = temp_copy;
-         ++code_end;
-         ++tempcount;
-+        _code._delete = true;
-     }
-     
-     _code._instr_count = code_end - code;
- }
- 
- 
- inline
- bool Machine::Code::decoder::validate_opcode(const opcode opc, const byte * const bc)
- {
-     if (opc >= MAX_OPCODE)
-     {
-         failure(invalid_opcode);
-         return false;
-     }
-     const opcode_t & op = Machine::getOpcodeTable()[opc];
-+    if (op.param_sz == VARARGS && bc >= _max.bytecode)
-+    {
-+        failure(arguments_exhausted);
-+        return false;
-+    }
-     const size_t param_sz = op.param_sz == VARARGS ? bc[0] + 1 : op.param_sz;
--    if (bc + param_sz > _max.bytecode)
-+    if (bc - 1 + param_sz >= _max.bytecode)
-     {
-         failure(arguments_exhausted);
-         return false;
-     }
-     return true;
- }
- 
- 
- bool Machine::Code::decoder::valid_upto(const uint16 limit, const uint16 x) const throw()
- {
-     const bool t = x < limit;
-     if (!t) failure(out_of_range_data);
-     return t;
- }
- 
-+bool Machine::Code::decoder::test_context() const throw()
-+{
-+    if (_pre_context >= _rule_length)
-+    {
-+        failure(out_of_range_data);
-+        return false;
-+    }
-+    return true;
-+}
- 
- inline 
- void Machine::Code::failure(const status_t s) throw() {
-     release_buffers();
-     _status = s;
- }
- 
- 
- inline
--void Machine::Code::decoder::analysis::set_ref(const int index) throw() {
--    contexts[index].flags.referenced = true;
--    if (index > max_ref) max_ref = index;
-+void Machine::Code::decoder::analysis::set_ref(int index, bool incinsert) throw() {
-+    if (incinsert && contexts[slotref].flags.inserted) --index;
-+    if (index + slotref < 0) return;
-+    contexts[index + slotref].flags.referenced = true;
-+    if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
- }
- 
- 
- inline
--void Machine::Code::decoder::analysis::set_changed(const int index) throw() {
--    contexts[index].flags.changed = true;
--    if (index > max_ref) max_ref = index;
-+void Machine::Code::decoder::analysis::set_noref(int index) throw() {
-+    if (contexts[slotref].flags.inserted) --index;
-+    if (index + slotref < 0) return;
-+    if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
-+}
-+
-+
-+inline
-+void Machine::Code::decoder::analysis::set_changed(int index) throw() {
-+    if (contexts[slotref].flags.inserted) --index;
-+    if (index + slotref < 0) return;
-+    contexts[index + slotref].flags.changed = true;
-+    if ((index > 0 || !contexts[index + slotref].flags.inserted) && index + slotref > max_ref) max_ref = index + slotref;
- }
- 
- 
- void Machine::Code::release_buffers() throw()
- {
--    free(_code);
--    free(_data);
-+    if (_own)
-+        free(_code);
-     _code = 0;
-     _data = 0;
-     _own  = false;
- }
- 
- 
- int32 Machine::Code::run(Machine & m, slotref * & map) const
- {
--    assert(_own);
-+//    assert(_own);
-     assert(*this);          // Check we are actually runnable
- 
--    if (m.slotMap().size() <= size_t(_max_ref + m.slotMap().context()))
-+    if (m.slotMap().size() <= size_t(_max_ref + m.slotMap().context())
-+        || m.slotMap()[_max_ref + m.slotMap().context()] == 0)
-     {
-         m._status = Machine::slot_offset_out_bounds;
--//        return (m.slotMap().end() - map);
-         return 1;
-+//        return m.run(_code, _data, map);
-     }
- 
-     return  m.run(_code, _data, map);
- }
- 
-diff --git a/gfx/graphite2/src/Collider.cpp b/gfx/graphite2/src/Collider.cpp
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/Collider.cpp
-@@ -0,0 +1,1088 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2010, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+#include <algorithm>
-+#include <limits>
-+#include <math.h>
-+#include <string>
-+#include <functional>
-+#include "inc/Collider.h"
-+#include "inc/Segment.h"
-+#include "inc/Slot.h"
-+#include "inc/GlyphCache.h"
-+#include "inc/Sparse.h"
-+
-+#define ISQRT2 0.707106781f
-+
-+// Possible rounding error for subbox boundaries: 0.016 = 1/64 = 1/256 * 4 
-+// (values in font range from 0..256)
-+// #define SUBBOX_RND_ERR 0.016
-+
-+using namespace graphite2;
-+
-+////    SHIFT-COLLIDER    ////
-+
-+// Initialize the Collider to hold the basic movement limits for the
-+// target slot, the one we are focusing on fixing.
-+bool ShiftCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float margin, float marginWeight,
-+    const Position &currShift, const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout)
-+{
-+    int i;
-+    float mx, mn;
-+    float a, shift;
-+    const GlyphCache &gc = seg->getFace()->glyphs();
-+    unsigned short gid = aSlot->gid();
-+    if (!gc.check(gid))
-+        return false;
-+    const BBox &bb = gc.getBoundingBBox(gid);
-+    const SlantBox &sb = gc.getBoundingSlantBox(gid);
-+    //float sx = aSlot->origin().x + currShift.x;
-+    //float sy = aSlot->origin().y + currShift.y;
-+    if (currOffset.x != 0.f || currOffset.y != 0.f)
-+        _limit = Rect(limit.bl - currOffset, limit.tr - currOffset);
-+    else
-+        _limit = limit;
-+    // For a ShiftCollider, these indices indicate which vector we are moving by:
-+    // each _ranges represents absolute space with respect to the origin of the slot. Thus take into account true origins but subtract the vmin for the slot
-+    for (i = 0; i < 4; ++i)
-+    {
-+        switch (i) {
-+            case 0 :	// x direction
-+                mn = _limit.bl.x + currOffset.x;
-+                mx = _limit.tr.x + currOffset.x;
-+                _len[i] = bb.xa - bb.xi;
-+                a = currOffset.y + currShift.y;
-+                _ranges[i].initialise<XY>(mn, mx, margin, marginWeight, a);
-+                break;
-+            case 1 :	// y direction
-+                mn = _limit.bl.y + currOffset.y;
-+                mx = _limit.tr.y + currOffset.y;
-+                _len[i] = bb.ya - bb.yi;
-+                a = currOffset.x + currShift.x;
-+                _ranges[i].initialise<XY>(mn, mx, margin, marginWeight, a);
-+                break;
-+            case 2 :	// sum (negatively sloped diagonal boundaries)
-+                // pick closest x,y limit boundaries in s direction
-+                shift = currOffset.x + currOffset.y + currShift.x + currShift.y;
-+                mn = -2 * min(currShift.x - _limit.bl.x, currShift.y - _limit.bl.y) + shift;
-+                mx = 2 * min(_limit.tr.x - currShift.x, _limit.tr.y - currShift.y) + shift;
-+                _len[i] = sb.sa - sb.si;
-+                a = currOffset.x - currOffset.y + currShift.x - currShift.y;
-+                _ranges[i].initialise<SD>(mn, mx, margin / ISQRT2, marginWeight, a);
-+                break;
-+            case 3 :	// diff (positively sloped diagonal boundaries)
-+                // pick closest x,y limit boundaries in d direction
-+                shift = currOffset.x - currOffset.y + currShift.x - currShift.y;
-+                mn = -2 * min(currShift.x - _limit.bl.x, _limit.tr.y - currShift.y) + shift;
-+                mx = 2 * min(_limit.tr.x - currShift.x, currShift.y - _limit.bl.y) + shift;
-+                _len[i] = sb.da - sb.di;
-+                a = currOffset.x + currOffset.y + currShift.x + currShift.y;
-+                _ranges[i].initialise<SD>(mn, mx, margin / ISQRT2, marginWeight, a);
-+                break;
-+        }
-+    }
-+
-+	_target = aSlot;
-+    if ((dir & 1) == 0)
-+    {
-+        // For LTR, switch and negate x limits.
-+        _limit.bl.x = -1 * limit.tr.x;
-+        //_limit.tr.x = -1 * limit.bl.x;
-+    }
-+    _currOffset = currOffset;
-+    _currShift = currShift;
-+    _origin = aSlot->origin() - currOffset;     // the original anchor position of the glyph
-+
-+	_margin = margin;
-+	_marginWt = marginWeight;
-+    
-+    SlotCollision *c = seg->collisionInfo(aSlot);
-+    _seqClass = c->seqClass();
-+	_seqProxClass = c->seqProxClass();
-+    _seqOrder = c->seqOrder();
-+    return true;
-+}
-+
-+template <class O>
-+float sdm(float vi, float va, float mx, float my, O op)
-+{
-+    float res = 2 * mx - vi;
-+    if (op(res, vi + 2 * my))
-+    {
-+        res = va + 2 * my;
-+        if (op(res, 2 * mx - va))
-+            res = mx + my;
-+    }
-+    return res;
-+}
-+
-+// Mark an area with a cost that can vary along the x or y axis. The region is expressed in terms of the centre of the target glyph in each axis
-+void ShiftCollider::addBox_slope(bool isx, const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, float weight, float m, bool minright, int axis)
-+{
-+    float a, c;
-+    switch (axis) {
-+        case 0 :
-+             if (box.bl.y < org.y + bb.ya && box.tr.y > org.y + bb.yi && box.width() > 0)
-+            {
-+                a = org.y + 0.5f * (bb.yi + bb.ya);
-+                c = 0.5f * (bb.xi + bb.xa);
-+                if (isx)
-+                    _ranges[axis].weighted<XY>(box.bl.x - c, box.tr.x - c, weight, a, m,
-+                                                (minright ? box.tr.x : box.bl.x) - c, a, 0, false);
-+                else
-+                    _ranges[axis].weighted<XY>(box.bl.x - c, box.tr.x - c, weight, a, 0, 0, org.y,
-+                                                m * (a * a + sqr((minright ? box.tr.y : box.bl.y) - 0.5f * (bb.yi + bb.ya))), false);
-+            }
-+            break;
-+        case 1 :
-+            if (box.bl.x < org.x + bb.xa && box.tr.x > org.x + bb.xi && box.height() > 0)
-+            {
-+                a = org.x + 0.5f * (bb.xi + bb.xa);
-+                c = 0.5f * (bb.yi + bb.ya);
-+                if (isx)
-+                    _ranges[axis].weighted<XY>(box.bl.y - c, box.tr.y - c, weight, a, 0, 0, org.x,
-+                                                m * (a * a + sqr((minright ? box.tr.x : box.bl.x) - 0.5f * (bb.xi + bb.xa))), false);
-+                else
-+                    _ranges[axis].weighted<XY>(box.bl.y - c, box.tr.y - c, weight, a, m, 
-+                                                (minright ? box.tr.y : box.bl.y) - c, a, 0, false);
-+            }
-+            break;
-+        case 2 :
-+            if (box.bl.x - box.tr.y < org.x - org.y + sb.da && box.tr.x - box.bl.y > org.x - org.y + sb.di)
-+            {
-+                float d = org.x - org.y + 0.5f * (sb.di + sb.da);
-+                c = 0.5f * (sb.si + sb.sa);
-+                float smax = min(2 * box.tr.x - d, 2 * box.tr.y + d);
-+                float smin = max(2 * box.bl.x - d, 2 * box.bl.y + d);
-+                if (smin > smax) return;
-+                float si;
-+                a = d;
-+                if (isx)
-+                    si = 2 * (minright ? box.tr.x : box.bl.x) - a;
-+                else
-+                    si = 2 * (minright ? box.tr.y : box.bl.y) + a;
-+                _ranges[axis].weighted<SD>(smin - c, smax - c, weight / 2, a, m / 2, si, 0, 0, isx);
-+            }
-+            break;
-+        case 3 :
-+            if (box.bl.x + box.bl.y < org.x + org.y + sb.sa && box.tr.x + box.tr.y > org.x + org.y + sb.si)
-+            {
-+                float s = org.x + org.y + 0.5f * (sb.si + sb.sa);
-+                c = 0.5f * (sb.di + sb.da);
-+                float dmax = min(2 * box.tr.x - s, s - 2 * box.bl.y);
-+                float dmin = max(2 * box.bl.x - s, s - 2 * box.tr.y);
-+                if (dmin > dmax) return;
-+                float di;
-+                a = s;
-+                if (isx)
-+                    di = 2 * (minright ? box.tr.x : box.bl.x) - a;
-+                else
-+                    di = 2 * (minright ? box.tr.y : box.bl.y) + a;
-+                _ranges[axis].weighted<SD>(dmin - c, dmax - c, weight / 2, a, m / 2, di, 0, 0, !isx);
-+            }
-+            break;
-+        default :
-+            break;
-+    }
-+    return;
-+}
-+
-+// Mark an area with an absolute cost, making it completely inaccessible.
-+inline void ShiftCollider::removeBox(const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, int axis)
-+{
-+    float c;
-+    switch (axis) {
-+        case 0 :
-+            if (box.bl.y < org.y + bb.ya && box.tr.y > org.y + bb.yi && box.width() > 0)
-+            {
-+                c = 0.5f * (bb.xi + bb.xa);
-+                _ranges[axis].exclude(box.bl.x - c, box.tr.x - c);
-+            }
-+            break;
-+        case 1 :
-+            if (box.bl.x < org.x + bb.xa && box.tr.x > org.x + bb.xi && box.height() > 0)
-+            {
-+                c = 0.5f * (bb.yi + bb.ya);
-+                _ranges[axis].exclude(box.bl.y - c, box.tr.y - c);
-+            }
-+            break;
-+        case 2 :
-+            if (box.bl.x - box.tr.y < org.x - org.y + sb.da && box.tr.x - box.bl.y > org.x - org.y + sb.di 
-+                && box.width() > 0 && box.height() > 0)
-+            {
-+                float di = org.x - org.y + sb.di;
-+                float da = org.x - org.y + sb.da;
-+                float smax = sdm(di, da, box.tr.x, box.tr.y, std::greater<float>());
-+                float smin = sdm(da, di, box.bl.x, box.bl.y, std::less<float>());
-+                c = 0.5f * (sb.si + sb.sa);
-+                _ranges[axis].exclude(smin - c, smax - c);
-+            }
-+            break;
-+        case 3 :
-+            if (box.bl.x + box.bl.y < org.x + org.y + sb.sa && box.tr.x + box.tr.y > org.x + org.y + sb.si 
-+                && box.width() > 0 && box.height() > 0)
-+            {
-+                float si = org.x + org.y + sb.si;
-+                float sa = org.x + org.y + sb.sa;
-+                float dmax = sdm(si, sa, box.tr.x, -box.bl.y, std::greater<float>());
-+                float dmin = sdm(sa, si, box.bl.x, -box.tr.y, std::less<float>());
-+                c = 0.5f * (sb.di + sb.da);
-+                _ranges[axis].exclude(dmin - c, dmax - c);
-+            }
-+            break;
-+        default :
-+            break;
-+    }
-+    return;
-+}
-+
-+// Adjust the movement limits for the target to avoid having it collide
-+// with the given neighbor slot. Also determine if there is in fact a collision
-+// between the target and the given slot.
-+bool ShiftCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift,
-+		bool isAfter,  // slot is logically after _target
-+		bool sameCluster, bool &hasCol, bool isExclusion,
-+        GR_MAYBE_UNUSED json * const dbgout )
-+{
-+    bool isCol = false;
-+    const float sx = slot->origin().x - _origin.x + currShift.x;
-+    const float sy = slot->origin().y - _origin.y + currShift.y;
-+    const float sd = sx - sy;
-+    const float ss = sx + sy;
-+    float vmin, vmax;
-+    float omin, omax, otmin, otmax;
-+    float cmin, cmax;   // target limits
-+    float torg;
-+    const GlyphCache &gc = seg->getFace()->glyphs();
-+    const unsigned short gid = slot->gid();
-+    if (!gc.check(gid))
-+        return false;
-+    const BBox &bb = gc.getBoundingBBox(gid);
-+
-+    SlotCollision * cslot = seg->collisionInfo(slot);
-+    int orderFlags = 0;
-+    bool sameClass = _seqProxClass == 0 && cslot->seqClass() == _seqClass;
-+    if (sameCluster && _seqClass 
-+        && (sameClass || (_seqProxClass != 0 && cslot->seqClass() == _seqProxClass)))
-+		// Force the target glyph to be in the specified direction from the slot we're testing.
-+        orderFlags = _seqOrder;
-+
-+    // short circuit if only interested in direct collision and we are out of range
-+    if (orderFlags || (sx + bb.xa + _margin >= _limit.bl.x && sx + bb.xi - _margin <= _limit.tr.x)
-+                    || (sy + bb.ya + _margin >= _limit.bl.y && sy + bb.yi - _margin <= _limit.tr.y))
-+
-+    {
-+        const float tx = _currOffset.x + _currShift.x;
-+        const float ty = _currOffset.y + _currShift.y;
-+        const float td = tx - ty;
-+        const float ts = tx + ty;
-+        const SlantBox &sb = gc.getBoundingSlantBox(gid);
-+        const unsigned short tgid = _target->gid();
-+        const BBox &tbb = gc.getBoundingBBox(tgid);
-+        const SlantBox &tsb = gc.getBoundingSlantBox(tgid);
-+        float seq_above_wt = cslot->seqAboveWt();
-+        float seq_below_wt = cslot->seqBelowWt();
-+        float seq_valign_wt = cslot->seqValignWt();
-+        // if isAfter, invert orderFlags for diagonal orders.
-+        if (isAfter)
-+        {
-+            // invert appropriate bits
-+            orderFlags ^= (sameClass ? 0x3F : 0x3);
-+            // consider 2 bits at a time, non overlapping. If both bits set, clear them
-+            orderFlags = orderFlags ^ ((((orderFlags >> 1) & orderFlags) & 0x15) * 3);
-+        }
-+
-+#if !defined GRAPHITE2_NTRACING
-+        if (dbgout)
-+            dbgout->setenv(0, slot);
-+#endif
-+
-+        // Process main bounding octabox.
-+        for (int i = 0; i < 4; ++i)
-+        {
-+            switch (i) {
-+                case 0 :	// x direction
-+                    vmin = max(max(bb.xi - tbb.xa + sx, sb.di - tsb.da + ty + sd), sb.si - tsb.sa - ty + ss);
-+                    vmax = min(min(bb.xa - tbb.xi + sx, sb.da - tsb.di + ty + sd), sb.sa - tsb.si - ty + ss);
-+                    otmin = tbb.yi + ty;
-+                    otmax = tbb.ya + ty;
-+                    omin = bb.yi + sy;
-+                    omax = bb.ya + sy;
-+                    torg = _currOffset.x;
-+                    cmin = _limit.bl.x + torg;
-+                    cmax = _limit.tr.x - tbb.xi + tbb.xa + torg;
-+                    break;
-+                case 1 :	// y direction
-+                    vmin = max(max(bb.yi - tbb.ya + sy, tsb.di - sb.da + tx - sd), sb.si - tsb.sa - tx + ss);
-+                    vmax = min(min(bb.ya - tbb.yi + sy, tsb.da - sb.di + tx - sd), sb.sa - tsb.si - tx + ss);
-+                    otmin = tbb.xi + tx;
-+                    otmax = tbb.xa + tx;
-+                    omin = bb.xi + sx;
-+                    omax = bb.xa + sx;
-+                    torg = _currOffset.y;
-+                    cmin = _limit.bl.y + torg;
-+                    cmax = _limit.tr.y - tbb.yi + tbb.ya + torg;
-+                    break;
-+                case 2 :    // sum - moving along the positively-sloped vector, so the boundaries are the
-+                            // negatively-sloped boundaries.
-+                    vmin = max(max(sb.si - tsb.sa + ss, 2 * (bb.yi - tbb.ya + sy) + td), 2 * (bb.xi - tbb.xa + sx) - td);
-+                    vmax = min(min(sb.sa - tsb.si + ss, 2 * (bb.ya - tbb.yi + sy) + td), 2 * (bb.xa - tbb.xi + sx) - td);
-+                    otmin = tsb.di + td;
-+                    otmax = tsb.da + td;
-+                    omin = sb.di + sd;
-+                    omax = sb.da + sd;
-+                    torg = _currOffset.x + _currOffset.y;
-+                    cmin = _limit.bl.x + _limit.bl.y + torg;
-+                    cmax = _limit.tr.x + _limit.tr.y - tsb.si + tsb.sa + torg;
-+                    break;
-+                case 3 :    // diff - moving along the negatively-sloped vector, so the boundaries are the
-+                            // positively-sloped boundaries.
-+                    vmin = max(max(sb.di - tsb.da + sd, 2 * (bb.xi - tbb.xa + sx) - ts), -2 * (bb.ya - tbb.yi + sy) + ts);
-+                    vmax = min(min(sb.da - tsb.di + sd, 2 * (bb.xa - tbb.xi + sx) - ts), -2 * (bb.yi - tbb.ya + sy) + ts);
-+                    otmin = tsb.si + ts;
-+                    otmax = tsb.sa + ts;
-+                    omin = sb.si + ss;
-+                    omax = sb.sa + ss;
-+                    torg = _currOffset.x - _currOffset.y;
-+                    cmin = _limit.bl.x - _limit.tr.y + torg;
-+                    cmax = _limit.tr.x - _limit.bl.y - tsb.di + tsb.da + torg;
-+                    break;
-+                default :
-+                    continue;
-+            }
-+            
-+#if !defined GRAPHITE2_NTRACING
-+            if (dbgout)
-+                dbgout->setenv(1, reinterpret_cast<void *>(-1));
-+#define DBGTAG(x) if (dbgout) dbgout->setenv(1, reinterpret_cast<void *>(-x));
-+#else
-+#define DBGTAG(x)
-+#endif
-+
-+            if (orderFlags)
-+            {
-+                Position org(tx, ty);
-+                float xminf = _limit.bl.x + _currOffset.x + tbb.xi;
-+                float xpinf = _limit.tr.x + _currOffset.x + tbb.xa;
-+                float ypinf = _limit.tr.y + _currOffset.y + tbb.ya;
-+                float yminf = _limit.bl.y + _currOffset.y + tbb.yi;
-+                switch (orderFlags) {
-+                    case SlotCollision::SEQ_ORDER_RIGHTUP :
-+                    {
-+                        float r1Xedge = cslot->seqAboveXoff() + 0.5f * (bb.xi + bb.xa) + sx;
-+                        float r3Xedge = cslot->seqBelowXlim() + bb.xa + sx + 0.5f * (tbb.xa - tbb.xi);
-+                        float r2Yedge = 0.5f * (bb.yi + bb.ya) + sy;
-+                        
-+                        // DBGTAG(1x) means the regions are up and right
-+                        // region 1
-+                        DBGTAG(11)
-+                        addBox_slope(true, Rect(Position(xminf, r2Yedge), Position(r1Xedge, ypinf)),
-+                                        tbb, tsb, org, 0, seq_above_wt, true, i);
-+                        // region 2
-+                        DBGTAG(12)
-+                        removeBox(Rect(Position(xminf, yminf), Position(r3Xedge, r2Yedge)), tbb, tsb, org, i);
-+                        // region 3, which end is zero is irrelevant since m weight is 0
-+                        DBGTAG(13)
-+                        addBox_slope(true, Rect(Position(r3Xedge, yminf), Position(xpinf, r2Yedge - cslot->seqValignHt())),
-+                                        tbb, tsb, org, seq_below_wt, 0, true, i);
-+                        // region 4
-+                        DBGTAG(14)
-+                        addBox_slope(false, Rect(Position(sx + bb.xi, r2Yedge), Position(xpinf, r2Yedge + cslot->seqValignHt())),
-+                                        tbb, tsb, org, 0, seq_valign_wt, true, i);
-+                        // region 5
-+                        DBGTAG(15)
-+                        addBox_slope(false, Rect(Position(sx + bb.xi, r2Yedge - cslot->seqValignHt()), Position(xpinf, r2Yedge)),
-+                                        tbb, tsb, org, seq_below_wt, seq_valign_wt, false, i);
-+                        break;
-+                    }
-+                    case SlotCollision::SEQ_ORDER_LEFTDOWN :
-+                    {
-+                        float r1Xedge = 0.5f * (bb.xi + bb.xa) + cslot->seqAboveXoff() + sx;
-+                        float r3Xedge = bb.xi - cslot->seqBelowXlim() + sx - 0.5f * (tbb.xa - tbb.xi);
-+                        float r2Yedge = 0.5f * (bb.yi + bb.ya) + sy;
-+                        // DBGTAG(2x) means the regions are up and right
-+                        // region 1
-+                        DBGTAG(21)
-+                        addBox_slope(true, Rect(Position(r1Xedge, yminf), Position(xpinf, r2Yedge)),
-+                                        tbb, tsb, org, 0, seq_above_wt, false, i);
-+                        // region 2
-+                        DBGTAG(22)
-+                        removeBox(Rect(Position(r3Xedge, r2Yedge), Position(xpinf, ypinf)), tbb, tsb, org, i);
-+                        // region 3
-+                        DBGTAG(23)
-+                        addBox_slope(true, Rect(Position(xminf, r2Yedge - cslot->seqValignHt()), Position(r3Xedge, ypinf)),
-+                                        tbb, tsb, org, seq_below_wt, 0, false, i);
-+                        // region 4
-+                        DBGTAG(24)
-+                        addBox_slope(false, Rect(Position(xminf, r2Yedge), Position(sx + bb.xa, r2Yedge + cslot->seqValignHt())),
-+                                        tbb, tsb, org, 0, seq_valign_wt, true, i);
-+                        // region 5
-+                        DBGTAG(25)
-+                        addBox_slope(false, Rect(Position(xminf, r2Yedge - cslot->seqValignHt()),
-+                                        Position(sx + bb.xa, r2Yedge)), tbb, tsb, org, seq_below_wt, seq_valign_wt, false, i);
-+                        break;
-+                    }
-+                    case SlotCollision::SEQ_ORDER_NOABOVE : // enforce neighboring glyph being above
-+                        DBGTAG(31);
-+                        removeBox(Rect(Position(bb.xi - tbb.xa + sx, sy + bb.ya), 
-+                                        Position(bb.xa - tbb.xi + sx, ypinf)), tbb, tsb, org, i);
-+                        break;
-+                    case SlotCollision::SEQ_ORDER_NOBELOW :	// enforce neighboring glyph being below
-+                        DBGTAG(32);
-+                        removeBox(Rect(Position(bb.xi - tbb.xa + sx, yminf),
-+                                        Position(bb.xa - tbb.xi + sx, sy + bb.yi)), tbb, tsb, org, i);
-+                        break;
-+                    case SlotCollision::SEQ_ORDER_NOLEFT :  // enforce neighboring glyph being to the left
-+                        DBGTAG(33)
-+                        removeBox(Rect(Position(xminf, bb.yi - tbb.ya + sy),
-+                                        Position(bb.xi - tbb.xa + sx, bb.ya - tbb.yi + sy)), tbb, tsb, org, i);
-+                        break;
-+                    case SlotCollision::SEQ_ORDER_NORIGHT : // enforce neighboring glyph being to the right
-+                        DBGTAG(34)
-+                        removeBox(Rect(Position(bb.xa - tbb.xi + sx, bb.yi - tbb.ya + sy),
-+                                        Position(xpinf, bb.ya - tbb.yi + sy)), tbb, tsb, org, i);
-+                        break;
-+                    default :
-+                        break;
-+                }
-+            }
-+
-+            if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
-+                continue;
-+
-+            // Process sub-boxes that are defined for this glyph.
-+            // We only need to do this if there was in fact a collision with the main octabox.
-+            uint8 numsub = gc.numSubBounds(gid);
-+            if (numsub > 0)
-+            {
-+                bool anyhits = false;
-+                for (int j = 0; j < numsub; ++j)
-+                {
-+                    const BBox &sbb = gc.getSubBoundingBBox(gid, j);
-+                    const SlantBox &ssb = gc.getSubBoundingSlantBox(gid, j);
-+                    switch (i) {
-+                        case 0 :    // x
-+                            vmin = max(max(sbb.xi-tbb.xa+sx, ssb.di-tsb.da+sd+ty), ssb.si-tsb.sa+ss-ty);
-+                            vmax = min(min(sbb.xa-tbb.xi+sx, ssb.da-tsb.di+sd+ty), ssb.sa-tsb.si+ss-ty);
-+                            omin = sbb.yi + sy;
-+                            omax = sbb.ya + sy;
-+                            break;
-+                        case 1 :    // y
-+                            vmin = max(max(sbb.yi-tbb.ya+sy, tsb.di-ssb.da-sd+tx), ssb.si-tsb.sa+ss-tx);
-+                            vmax = min(min(sbb.ya-tbb.yi+sy, tsb.da-ssb.di-sd+tx), ssb.sa-tsb.si+ss-tx);
-+                            omin = sbb.xi + sx;
-+                            omax = sbb.xa + sx;
-+                            break;
-+                        case 2 :    // sum
-+                            vmin = max(max(ssb.si-tsb.sa+ss, 2*(sbb.yi-tbb.ya+sy)+td), 2*(sbb.xi-tbb.xa+sx)-td);
-+                            vmax = min(min(ssb.sa-tsb.si+ss, 2*(sbb.ya-tbb.yi+sy)+td), 2*(sbb.xa-tbb.xi+sx)-td);
-+                            omin = ssb.di + sd;
-+                            omax = ssb.da + sd;
-+                            break;
-+                        case 3 :    // diff
-+                            vmin = max(max(ssb.di-tsb.da+sd, 2*(sbb.xi-tbb.xa+sx)-ts), -2*(sbb.ya-tbb.yi+sy)+ts);
-+                            vmax = min(min(ssb.da-tsb.di+sd, 2*(sbb.xa-tbb.xi+sx)-ts), -2*(sbb.yi-tbb.ya+sy)+ts);
-+                            omin = ssb.si + ss;
-+                            omax = ssb.sa + ss;
-+                            break;
-+                    }
-+                    if (vmax < cmin - _margin || vmin > cmax + _margin || omax < otmin - _margin || omin > otmax + _margin)
-+                        continue;
-+
-+#if !defined GRAPHITE2_NTRACING
-+                    if (dbgout)
-+                        dbgout->setenv(1, reinterpret_cast<void *>(j));
-+#endif
-+                    if (omin > otmax)
-+                        _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-+                                                sqr(_margin - omin + otmax) * _marginWt, false);
-+                    else if (omax < otmin)
-+                        _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-+                                                sqr(_margin - otmin + omax) * _marginWt, false);
-+                    else
-+                        _ranges[i].exclude_with_margins(vmin, vmax, i);
-+                    anyhits = true;
-+                }
-+                if (anyhits)
-+                    isCol = true;
-+            }
-+            else // no sub-boxes
-+            {
-+#if !defined GRAPHITE2_NTRACING
-+                    if (dbgout)
-+                        dbgout->setenv(1, reinterpret_cast<void *>(-1));
-+#endif
-+                isCol = true;
-+                if (omin > otmax)
-+                    _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-+                                            sqr(_margin - omin + otmax) * _marginWt, false);
-+                else if (omax < otmin)
-+                    _ranges[i].weightedAxis(i, vmin - _margin, vmax + _margin, 0, 0, 0, 0, 0,
-+                                            sqr(_margin - otmin + omax) * _marginWt, false);
-+                else
-+                    _ranges[i].exclude_with_margins(vmin, vmax, i);
-+
-+            }
-+        }
-+    }
-+    bool res = true;
-+    if (cslot->exclGlyph() > 0 && gc.check(cslot->exclGlyph()) && !isExclusion)
-+    {
-+        // Set up the bogus slot representing the exclusion glyph.
-+        Slot *exclSlot = seg->newSlot();
-+        exclSlot->setGlyph(seg, cslot->exclGlyph());
-+        Position exclOrigin(slot->origin() + cslot->exclOffset());
-+        exclSlot->origin(exclOrigin);
-+        res &= mergeSlot(seg, exclSlot, currShift, isAfter, sameCluster, isCol, true, dbgout );
-+        seg->freeSlot(exclSlot);
-+    }
-+    hasCol |= isCol;
-+    return res;
-+    
-+}   // end of ShiftCollider::mergeSlot
-+
-+
-+// Figure out where to move the target glyph to, and return the amount to shift by.
-+Position ShiftCollider::resolve(GR_MAYBE_UNUSED Segment *seg, bool &isCol, GR_MAYBE_UNUSED json * const dbgout)
-+{
-+    float tbase;
-+    float totalCost = (float)(std::numeric_limits<float>::max() / 2);
-+    Position resultPos = Position(0, 0);
-+#if !defined GRAPHITE2_NTRACING
-+	int bestAxis = -1;
-+    if (dbgout)
-+    {
-+		outputJsonDbgStartSlot(dbgout, seg);
-+        *dbgout << "vectors" << json::array;
-+    }
-+#endif
-+    isCol = true;
-+    for (int i = 0; i < 4; ++i)
-+    {
-+        float bestCost = -1;
-+        float bestPos;
-+        // Calculate the margin depending on whether we are moving diagonally or not:
-+        switch (i) {
-+            case 0 :	// x direction
-+                tbase = _currOffset.x;
-+                break;
-+            case 1 :	// y direction
-+                tbase = _currOffset.y;
-+                break;
-+            case 2 :	// sum (negatively-sloped diagonals)
-+                tbase = _currOffset.x + _currOffset.y;
-+                break;
-+            case 3 :	// diff (positively-sloped diagonals)
-+                tbase = _currOffset.x - _currOffset.y;
-+                break;
-+        }
-+        Position testp;
-+        bestPos = _ranges[i].closest(0, bestCost) - tbase;     // Get the best relative position
-+#if !defined GRAPHITE2_NTRACING
-+        if (dbgout)
-+            outputJsonDbgOneVector(dbgout, seg, i, tbase, bestCost, bestPos) ;
-+#endif
-+        if (bestCost >= 0.0f)
-+        {
-+            isCol = false;
-+            switch (i) {
-+                case 0 : testp = Position(bestPos, _currShift.y); break;
-+                case 1 : testp = Position(_currShift.x, bestPos); break;
-+                case 2 : testp = Position(0.5f * (_currShift.x - _currShift.y + bestPos), 0.5f * (_currShift.y - _currShift.x + bestPos)); break;
-+                case 3 : testp = Position(0.5f * (_currShift.x + _currShift.y + bestPos), 0.5f * (_currShift.x + _currShift.y - bestPos)); break;
-+            }
-+            if (bestCost < totalCost - 0.01f)
-+            {
-+                totalCost = bestCost;
-+                resultPos = testp;
-+#if !defined GRAPHITE2_NTRACING
-+                bestAxis = i;
-+#endif
-+            }
-+        }
-+    }  // end of loop over 4 directions
-+
-+#if !defined GRAPHITE2_NTRACING
-+    if (dbgout)
-+        outputJsonDbgEndSlot(dbgout, resultPos, bestAxis, isCol);
-+#endif
-+
-+    return resultPos;
-+
-+}   // end of ShiftCollider::resolve
-+
-+
-+#if !defined GRAPHITE2_NTRACING
-+
-+void ShiftCollider::outputJsonDbg(json * const dbgout, Segment *seg, int axis)
-+{
-+    int axisMax = axis;
-+    if (axis < 0) // output all axes
-+    {
-+        *dbgout << "gid" << _target->gid()
-+            << "limit" << _limit
-+            << "target" << json::object
-+                << "origin" << _target->origin()
-+                << "margin" << _margin
-+                << "bbox" << seg->theGlyphBBoxTemporary(_target->gid())
-+                << "slantbox" << seg->getFace()->glyphs().slant(_target->gid())
-+                << json::close; // target object
-+        *dbgout << "ranges" << json::array;
-+        axis = 0;
-+        axisMax = 3;
-+    }
-+    for (int iAxis = axis; iAxis <= axisMax; ++iAxis)
-+    {
-+        *dbgout << json::flat << json::array << _ranges[iAxis].position();
-+        for (Zones::const_iterator s = _ranges[iAxis].begin(), e = _ranges[iAxis].end(); s != e; ++s)
-+            *dbgout << json::flat << json::array 
-+                        << Position(s->x, s->xm) << s->sm << s->smx << s->c
-+                    << json::close;
-+        *dbgout << json::close;
-+    }
-+    if (axis < axisMax) // looped through the _ranges array for all axes
-+        *dbgout << json::close; // ranges array
-+}
-+
-+void ShiftCollider::outputJsonDbgStartSlot(json * const dbgout, Segment *seg)
-+{
-+        *dbgout << json::object // slot - not closed till the end of the caller method
-+                << "slot" << objectid(dslot(seg, _target))
-+				<< "gid" << _target->gid()
-+                << "limit" << _limit
-+                << "target" << json::object
-+                    << "origin" << _origin
-+                    << "currShift" << _currShift
-+                    << "currOffset" << seg->collisionInfo(_target)->offset()
-+                    << "bbox" << seg->theGlyphBBoxTemporary(_target->gid())
-+                    << "slantBox" << seg->getFace()->glyphs().slant(_target->gid())
-+                    << "fix" << "shift";
-+        *dbgout     << json::close; // target object
-+}
-+
-+void ShiftCollider::outputJsonDbgEndSlot(GR_MAYBE_UNUSED json * const dbgout,
-+	 Position resultPos, int bestAxis, bool isCol)
-+{
-+    *dbgout << json::close // vectors array
-+    << "result" << resultPos
-+	//<< "scraping" << _scraping[bestAxis]
-+	<< "bestAxis" << bestAxis
-+    << "stillBad" << isCol
-+    << json::close; // slot object
-+}
-+
-+void ShiftCollider::outputJsonDbgOneVector(json * const dbgout, Segment *seg, int axis,
-+	float tleft, float bestCost, float bestVal) 
-+{
-+	const char * label;
-+	switch (axis)
-+	{
-+		case 0:	label = "x";			break;
-+		case 1:	label = "y";			break;
-+		case 2:	label = "sum (NE-SW)";	break;
-+		case 3:	label = "diff (NW-SE)";	break;
-+		default: label = "???";			break;
-+	}
-+
-+	*dbgout << json::object // vector
-+		<< "direction" << label
-+		<< "targetMin" << tleft;
-+            
-+	outputJsonDbgRemovals(dbgout, axis, seg);
-+    	
-+    *dbgout << "ranges";
-+    outputJsonDbg(dbgout, seg, axis);
-+
-+    *dbgout << "bestCost" << bestCost
-+        << "bestVal" << bestVal + tleft
-+        << json::close; // vectors object
-+}
-+
-+void ShiftCollider::outputJsonDbgRemovals(json * const dbgout, int axis, Segment *seg)
-+{
-+    *dbgout << "removals" << json::array;
-+    _ranges[axis].jsonDbgOut(seg);
-+    *dbgout << json::close; // removals array
-+}
-+
-+#endif // !defined GRAPHITE2_NTRACING
-+
-+
-+////    KERN-COLLIDER    ////
-+
-+inline
-+static float localmax (float al, float au, float bl, float bu, float x)
-+{
-+    if (al < bl)
-+    { if (au < bu) return au < x ? au : x; }
-+    else if (au > bu) return bl < x ? bl : x;
-+    return x;
-+}
-+
-+inline
-+static float localmin(float al, float au, float bl, float bu, float x)
-+{
-+    if (bl > al)
-+    { if (bu > au) return bl > x ? bl : x; }
-+    else if (au > bu) return al > x ? al : x;
-+    return x;        
-+}
-+
-+// Return the given edge of the glyph at height y, taking any slant box into account.
-+static float get_edge(Segment *seg, const Slot *s, const Position &shift, float y, float width, bool isRight)
-+{
-+    const GlyphCache &gc = seg->getFace()->glyphs();
-+    unsigned short gid = s->gid();
-+    float sx = s->origin().x + shift.x;
-+    float sy = s->origin().y + shift.y;
-+    uint8 numsub = gc.numSubBounds(gid);
-+    float res = isRight ? (float)-1e38 : (float)1e38;
-+
-+    if (numsub > 0)
-+    {
-+        for (int i = 0; i < numsub; ++i)
-+        {
-+            const BBox &sbb = gc.getSubBoundingBBox(gid, i);
-+            const SlantBox &ssb = gc.getSubBoundingSlantBox(gid, i);
-+            if (sy + sbb.yi > y + width / 2 || sy + sbb.ya < y - width / 2)
-+                continue;
-+            if (isRight)
-+            {
-+                float x = sx + sbb.xa;
-+                if (x > res)
-+                {
-+                    float td = sx - sy + ssb.da + y;
-+                    float ts = sx + sy + ssb.sa - y;
-+                    x = localmax(td - width / 2, td + width / 2,  ts - width / 2, ts + width / 2, x);
-+                    if (x > res)
-+                        res = x;
-+                }
-+            }
-+            else
-+            {
-+                float x = sx + sbb.xi;
-+                if (x < res)
-+                {
-+                    float td = sx - sy + ssb.di + y;
-+                    float ts = sx + sy + ssb.si - y;
-+                    x = localmin(td - width / 2, td + width / 2, ts - width / 2, ts + width / 2, x);
-+                    if (x < res)
-+                        res = x;
-+                }
-+            }
-+        }
-+    }
-+    else
-+    {
-+        const BBox &bb = gc.getBoundingBBox(gid);
-+        const SlantBox &sb = gc.getBoundingSlantBox(gid);
-+        float td = sx - sy + y;
-+        float ts = sx + sy - y;
-+        if (isRight)
-+            res = localmax(td + sb.da - width / 2, td + sb.da + width / 2, ts + sb.sa - width / 2, ts + sb.sa + width / 2, sx + bb.xa);
-+        else
-+            res = localmin(td + sb.di - width / 2, td + sb.di + width / 2, ts + sb.si - width / 2, ts + sb.si + width / 2, sx + bb.xi);
-+    }
-+    return res;
-+}
-+
-+
-+bool KernCollider::initSlot(Segment *seg, Slot *aSlot, const Rect &limit, float margin,
-+    const Position &currShift, const Position &offsetPrev, int dir,
-+    float ymin, float ymax, GR_MAYBE_UNUSED json * const dbgout)
-+{
-+    const GlyphCache &gc = seg->getFace()->glyphs();
-+    const Slot *base = aSlot;
-+    // const Slot *last = aSlot;
-+    const Slot *s;
-+    int numSlices;
-+    while (base->attachedTo())
-+        base = base->attachedTo();
-+    if (margin < 10) margin = 10;
-+
-+    _limit = limit;
-+    _offsetPrev = offsetPrev; // kern from a previous pass
-+    
-+    // Calculate the height of the glyph and how many horizontal slices to use.
-+    if (_maxy >= 1e37f)
-+    {
-+        _maxy = ymax;
-+        _miny = ymin;
-+        _sliceWidth = margin / 1.5f;
-+        numSlices = int((_maxy - _miny + 2) / (_sliceWidth / 1.5f) + 1.f);  // +2 helps with rounding errors
-+        _edges.clear();
-+        _edges.insert(_edges.begin(), numSlices, (dir & 1) ? 1e38f : -1e38f);
-+        _xbound = (dir & 1) ? (float)1e38f : (float)-1e38f;
-+    }
-+    else if (_maxy != ymax || _miny != ymin)
-+    {
-+        if (_miny != ymin)
-+        {
-+            numSlices = int((ymin - _miny) / _sliceWidth - 1);
-+            _miny += numSlices * _sliceWidth;
-+            if (numSlices < 0)
-+                _edges.insert(_edges.begin(), -numSlices, (dir & 1) ? 1e38f : -1e38f);
-+            else if ((unsigned)numSlices < _edges.size())    // this shouldn't fire since we always grow the range
-+            {
-+                Vector<float>::iterator e = _edges.begin();
-+                while (numSlices--)
-+                    ++e;
-+                _edges.erase(_edges.begin(), e);
-+            }
-+        }
-+        if (_maxy != ymax)
-+        {
-+            numSlices = int((ymax - _miny) / _sliceWidth + 1);
-+            _maxy = numSlices * _sliceWidth + _miny;
-+            if (numSlices > (int)_edges.size())
-+                _edges.insert(_edges.end(), numSlices - _edges.size(), (dir & 1) ? 1e38f : -1e38f);
-+            else if (numSlices < (int)_edges.size())   // this shouldn't fire since we always grow the range
-+            {
-+                while ((int)_edges.size() > numSlices)
-+                    _edges.pop_back();
-+            }
-+        }
-+    }
-+    numSlices = _edges.size();
-+
-+#if !defined GRAPHITE2_NTRACING
-+    // Debugging
-+    _seg = seg;
-+    _slotNear.clear();
-+    _slotNear.insert(_slotNear.begin(), numSlices, NULL);
-+    _nearEdges.clear();
-+    _nearEdges.insert(_nearEdges.begin(), numSlices, (dir & 1) ? -1e38f : +1e38f);
-+#endif
-+    
-+    // Determine the trailing edge of each slice (ie, left edge for a RTL glyph).
-+    for (s = base; s; s = s->nextInCluster(s))
-+    {
-+        SlotCollision *c = seg->collisionInfo(s);
-+        if (!gc.check(s->gid()))
-+            return false;
-+        const BBox &bs = gc.getBoundingBBox(s->gid());
-+        float x = s->origin().x + c->shift().x + ((dir & 1) ? bs.xi : bs.xa);
-+        // Loop over slices.
-+        // Note smin might not be zero if glyph s is not at the bottom of the cluster; similarly for smax.
-+        float toffset = c->shift().y - _miny + 1 + s->origin().y;
-+        int smin = max(0, int((bs.yi + toffset) / _sliceWidth));
-+        int smax = min(numSlices - 1, int((bs.ya + toffset) / _sliceWidth + 1));
-+        for (int i = smin; i <= smax; ++i)
-+        {
-+            float t;
-+            float y = _miny - 1 + (i + .5f) * _sliceWidth; // vertical center of slice
-+            if ((dir & 1) && x < _edges[i])
-+            {
-+                t = get_edge(seg, s, c->shift(), y, _sliceWidth, false);
-+                if (t < _edges[i])
-+                {
-+                    _edges[i] = t;
-+                    if (t < _xbound)
-+                        _xbound = t;
-+                }
-+            }
-+            else if (!(dir & 1) && x > _edges[i])
-+            {
-+                t = get_edge(seg, s, c->shift(), y, _sliceWidth, true);
-+                if (t > _edges[i])
-+                {
-+                    _edges[i] = t;
-+                    if (t > _xbound)
-+                        _xbound = t;
-+                }
-+            }
-+        }
-+    }
-+    _mingap = (float)1e38;
-+    _target = aSlot;
-+    _margin = margin;
-+    _currShift = currShift;
-+    return true;
-+}   // end of KernCollider::initSlot
-+
-+
-+// Determine how much the target slot needs to kern away from the given slot.
-+// In other words, merge information from given slot's position with what the target slot knows
-+// about how it can kern.
-+// Return false if we know there is no collision, true if we think there might be one.
-+bool KernCollider::mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, GR_MAYBE_UNUSED json * const dbgout)
-+{
-+    int rtl = (dir & 1) * 2 - 1;
-+    if (!seg->getFace()->glyphs().check(slot->gid()))
-+        return false;
-+    const Rect &bb = seg->theGlyphBBoxTemporary(slot->gid());
-+    const float sx = slot->origin().x + currShift.x;
-+    float x = sx + (rtl > 0 ? bb.tr.x : bb.bl.x);
-+    // this isn't going to reduce _mingap so skip
-+    if ((rtl > 0 && x < _xbound - _mingap - currSpace) || (rtl <= 0 && x > _xbound + _mingap + currSpace))
-+        return false;
-+
-+    const float sy = slot->origin().y + currShift.y;
-+    int smin = max(0, int((bb.bl.y + (1 - _miny + sy)) / _sliceWidth + 1));
-+    int smax = min((int)_edges.size() - 1, int((bb.tr.y + (1 - _miny + sy)) / _sliceWidth + 1));
-+    bool collides = false;
-+
-+    for (int i = smin; i <= smax; ++i)
-+    {
-+        float t;
-+        float y = (float)(_miny - 1 + (i + .5f) * _sliceWidth);  // vertical center of slice
-+        if (x * rtl > _edges[i] * rtl - _mingap - currSpace)
-+        {
-+            // 2 * currSpace to account for the space that is already separating them and the space we want to add
-+            float m = get_edge(seg, slot, currShift, y, _sliceWidth, rtl > 0) + 2 * rtl * currSpace;
-+            t = rtl * (_edges[i] - m);
-+            // Check slices above and below (if any).
-+            if (i < (int)_edges.size() - 1) t = min(t, rtl * (_edges[i+1] - m));
-+            if (i > 0) t = min(t, rtl * (_edges[i-1] - m));
-+            // _mingap is positive to shrink
-+            if (t < _mingap)
-+            {
-+                _mingap = t;
-+                collides = true;
-+            }
-+#if !defined GRAPHITE2_NTRACING
-+            // Debugging - remember the closest neighboring edge for this slice.
-+            if (rtl * m > rtl * _nearEdges[i])
-+            {
-+                _slotNear[i] = slot;
-+                _nearEdges[i] = m;
-+            }
-+#endif
-+        }
-+    }
-+    return collides;   // note that true is not a necessarily reliable value
-+    
-+}   // end of KernCollider::mergeSlot
-+
-+
-+// Return the amount to kern by.
-+Position KernCollider::resolve(GR_MAYBE_UNUSED Segment *seg, GR_MAYBE_UNUSED Slot *slot,
-+        int dir, float margin, GR_MAYBE_UNUSED json * const dbgout)
-+{
-+    float resultNeeded = (1 - 2 * (dir & 1)) * (_mingap - margin);
-+    float result = min(_limit.tr.x - _offsetPrev.x, max(resultNeeded, _limit.bl.x - _offsetPrev.x));
-+
-+#if !defined GRAPHITE2_NTRACING
-+    if (dbgout)
-+    {
-+        *dbgout << json::object // slot
-+                << "slot" << objectid(dslot(seg, _target))
-+				<< "gid" << _target->gid()
-+                << "margin" << _margin
-+                << "limit" << _limit
-+                << "miny" << _miny
-+                << "maxy" << _maxy
-+                << "slicewidth" << _sliceWidth
-+                << "target" << json::object
-+                    << "origin" << _target->origin()
-+                    //<< "currShift" << _currShift
-+                    << "offsetPrev" << _offsetPrev
-+                    << "bbox" << seg->theGlyphBBoxTemporary(_target->gid())
-+                    << "slantBox" << seg->getFace()->glyphs().slant(_target->gid())
-+                    << "fix" << "kern"
-+                    << json::close; // target object
-+        
-+        *dbgout << "slices" << json::array;
-+        for (int is = 0; is < (int)_edges.size(); is++)
-+        {
-+            *dbgout << json::flat << json::object 
-+                << "i" << is 
-+                << "targetEdge" << _edges[is]
-+                << "neighbor" << objectid(dslot(seg, _slotNear[is]))
-+                << "nearEdge" << _nearEdges[is] 
-+                << json::close;
-+        }
-+        *dbgout << json::close; // slices array
-+            
-+        *dbgout
-+            << "xbound" << _xbound
-+            << "minGap" << _mingap
-+            << "needed" << resultNeeded
-+            << "result" << result
-+            << "stillBad" << (result != resultNeeded)
-+            << json::close; // slot object
-+    }
-+#endif
-+
-+    return Position(result, 0.);
-+    
-+}   // end of KernCollider::resolve
-+
-+void KernCollider::shift(const Position &mv, int dir)
-+{
-+    for (Vector<float>::iterator e = _edges.begin(); e != _edges.end(); ++e)
-+        *e += mv.x;
-+    _xbound += (1 - 2 * (dir & 1)) * mv.x;
-+}
-+
-+////    SLOT-COLLISION    ////
-+
-+// Initialize the collision attributes for the given slot.
-+SlotCollision::SlotCollision(Segment *seg, Slot *slot)
-+{
-+    initFromSlot(seg, slot);
-+}
-+
-+void SlotCollision::initFromSlot(Segment *seg, Slot *slot)
-+{
-+    // Initialize slot attributes from glyph attributes.
-+	// The order here must match the order in the grcompiler code, 
-+	// GrcSymbolTable::AssignInternalGlyphAttrIDs.
-+    uint16 gid = slot->gid();
-+    uint16 aCol = seg->silf()->aCollision(); // flags attr ID
-+    const GlyphFace * glyphFace = seg->getFace()->glyphs().glyphSafe(gid);
-+    if (!glyphFace)
-+        return;
-+    const sparse &p = glyphFace->attrs();
-+    _flags = p[aCol];
-+    _limit = Rect(Position(p[aCol+1], p[aCol+2]),
-+                  Position(p[aCol+3], p[aCol+4]));
-+    _margin = p[aCol+5];
-+    _marginWt = p[aCol+6];
-+
-+    _seqClass = p[aCol+7];
-+	_seqProxClass = p[aCol+8];
-+    _seqOrder = p[aCol+9];
-+	_seqAboveXoff = p[aCol+10];
-+	_seqAboveWt = p[aCol+11];
-+	_seqBelowXlim = p[aCol+12];
-+	_seqBelowWt = p[aCol+13];
-+	_seqValignHt = p[aCol+14];
-+	_seqValignWt = p[aCol+15];    
-+
-+    // These attributes do not have corresponding glyph attribute:
-+    _exclGlyph = 0;
-+    _exclOffset = Position(0, 0);
-+}
-+
-+float SlotCollision::getKern(int dir) const
-+{
-+    if ((_flags & SlotCollision::COLL_KERN) != 0)
-+        return float(_shift.x * ((dir & 1) ? -1 : 1));
-+    else
-+    	return 0;
-+}
-+
-diff --git a/gfx/graphite2/src/Decompressor.cpp b/gfx/graphite2/src/Decompressor.cpp
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/Decompressor.cpp
-@@ -0,0 +1,113 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2015, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+#include <cassert>
-+
-+#include "inc/Decompressor.h"
-+#include "inc/Compression.h"
-+
-+using namespace lz4;
-+
-+namespace {
-+
-+inline
-+u32 read_literal(u8 const * &s, u8 const * const e, u32 l) {
-+    if (l == 15 && s != e)
-+    {
-+        u8 b = 0;
-+        do { l += b = *s++; } while(b==0xff && s != e);
-+    }
-+    return l;
-+}
-+
-+bool read_sequence(u8 const * &src, u8 const * const end, u8 const * &literal, u32 & literal_len, u32 & match_len, u32 & match_dist)
-+{
-+    u8 const token = *src++;
-+    
-+    literal_len = read_literal(src, end, token >> 4);
-+    literal = src;
-+    src += literal_len;
-+    
-+    if (src > end - 2)
-+        return false;
-+    
-+    match_dist  = *src++;
-+    match_dist |= *src++ << 8;
-+    match_len = read_literal(src, end, token & 0xf);
-+    
-+    return src <= end-5;
-+}
-+
-+}
-+
-+int lz4::decompress(void const *in, size_t in_size, void *out, size_t out_size)
-+{
-+    if (out_size <= in_size || in_size < sizeof(unsigned long)+1)
-+        return -1;
-+    
-+    u8 const *       src     = static_cast<u8 const *>(in),
-+             *       literal = 0,
-+             * const src_end = src + in_size;
-+
-+    u8 *       dst     = static_cast<u8*>(out),
-+       * const dst_end = dst + out_size;
-+    
-+    u32 literal_len = 0,
-+        match_len = 0,
-+        match_dist = 0;
-+    
-+    while (read_sequence(src, src_end, literal, literal_len, match_len, match_dist))
-+    {
-+        if (literal_len != 0)
-+        {
-+            // Copy in literal. At this point the last full sequence must be at
-+            // least MINMATCH + 5 from the end of the output buffer.
-+            if (dst + align(literal_len) > dst_end - (MINMATCH+5))
-+                return -1;
-+            dst = overrun_copy(dst, literal, literal_len);
-+        }
-+        
-+        // Copy, possibly repeating, match from earlier in the
-+        //  decoded output.
-+        u8 const * const pcpy = dst - match_dist;
-+        if (pcpy < static_cast<u8*>(out)
-+                  || dst + match_len + MINMATCH > dst_end - 5)
-+            return -1;
-+        if (dst > pcpy+sizeof(unsigned long) 
-+            && dst + align(match_len + MINMATCH) <= dst_end)
-+            dst = overrun_copy(dst, pcpy, match_len + MINMATCH);
-+        else 
-+            dst = safe_copy(dst, pcpy, match_len + MINMATCH);
-+    }
-+    
-+    if (literal + literal_len > src_end
-+              || dst + literal_len > dst_end)
-+        return -1;
-+    dst = fast_copy(dst, literal, literal_len);
-+    
-+    return dst - (u8*)out;
-+}
-+
-diff --git a/gfx/graphite2/src/Face.cpp b/gfx/graphite2/src/Face.cpp
---- a/gfx/graphite2/src/Face.cpp
-+++ b/gfx/graphite2/src/Face.cpp
-@@ -23,28 +23,39 @@ Alternatively, the contents of this file
- Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
- #include <cstring>
- #include "graphite2/Segment.h"
- #include "inc/CmapCache.h"
- #include "inc/debug.h"
-+#include "inc/Decompressor.h"
- #include "inc/Endian.h"
- #include "inc/Face.h"
- #include "inc/FileFace.h"
- #include "inc/GlyphFace.h"
- #include "inc/json.h"
- #include "inc/SegCacheStore.h"
- #include "inc/Segment.h"
- #include "inc/NameTable.h"
- #include "inc/Error.h"
- 
- using namespace graphite2;
- 
-+namespace
-+{
-+enum compression
-+{
-+    NONE,
-+    LZ4
-+};
-+
-+}
-+
- Face::Face(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops)
- : m_appFaceHandle(appFaceHandle),
-   m_pFileFace(NULL),
-   m_pGlyphFaceCache(NULL),
-   m_cmap(NULL),
-   m_pNames(NULL),
-   m_logger(NULL),
-   m_error(0), m_errcntxt(0),
-@@ -79,55 +90,59 @@ float Face::default_glyph_advance(const 
- 
- bool Face::readGlyphs(uint32 faceOptions)
- {
-     Error e;
- #ifdef GRAPHITE2_TELEMETRY
-     telemetry::category _glyph_cat(tele.glyph);
- #endif
-     error_context(EC_READGLYPHS);
-+    m_pGlyphFaceCache = new GlyphCache(*this, faceOptions);
-+
-+    if (e.test(!m_pGlyphFaceCache, E_OUTOFMEM)
-+        || e.test(m_pGlyphFaceCache->numGlyphs() == 0, E_NOGLYPHS)
-+        || e.test(m_pGlyphFaceCache->unitsPerEm() == 0, E_BADUPEM))
-+    {
-+        return error(e);
-+    }
-+
-     if (faceOptions & gr_face_cacheCmap)
-         m_cmap = new CachedCmap(*this);
-     else
-         m_cmap = new DirectCmap(*this);
--
--    m_pGlyphFaceCache = new GlyphCache(*this, faceOptions);
--    if (e.test(!m_pGlyphFaceCache, E_OUTOFMEM)
--        || e.test(m_pGlyphFaceCache->numGlyphs() == 0, E_NOGLYPHS)
--        || e.test(m_pGlyphFaceCache->unitsPerEm() == 0, E_BADUPEM)
--        || e.test(!m_cmap, E_OUTOFMEM) || e.test(!*m_cmap, E_BADCMAP))
--    {
-+    if (e.test(!m_cmap, E_OUTOFMEM) || e.test(!*m_cmap, E_BADCMAP))
-         return error(e);
--    }
- 
-     if (faceOptions & gr_face_preloadGlyphs)
-         nameTable();        // preload the name table along with the glyphs.
- 
-     return true;
- }
- 
- bool Face::readGraphite(const Table & silf)
- {
- #ifdef GRAPHITE2_TELEMETRY
-     telemetry::category _silf_cat(tele.silf);
- #endif
-     Error e;
-     error_context(EC_READSILF);
-     const byte * p = silf;
--    if (e.test(!p, E_NOSILF)) return error(e);
-+    if (e.test(!p, E_NOSILF) || e.test(silf.size() < 20, E_BADSIZE)) return error(e);
- 
-     const uint32 version = be::read<uint32>(p);
-     if (e.test(version < 0x00020000, E_TOOOLD)) return error(e);
-     if (version >= 0x00030000)
-         be::skip<uint32>(p);        // compilerVersion
-     m_numSilf = be::read<uint16>(p);
-+
-     be::skip<uint16>(p);            // reserved
- 
-     bool havePasses = false;
-     m_silfs = new Silf[m_numSilf];
-+    if (e.test(!m_silfs, E_OUTOFMEM)) return error(e);
-     for (int i = 0; i < m_numSilf; i++)
-     {
-         error_context(EC_ASILF + (i << 8));
-         const uint32 offset = be::read<uint32>(p),
-                      next   = i == m_numSilf - 1 ? silf.size() : be::peek<uint32>(p);
-         if (e.test(next > silf.size() || offset >= next, E_BADSIZE))
-             return error(e);
- 
-@@ -153,29 +168,38 @@ bool Face::runGraphite(Segment *seg, con
-     if (dbgout)
-     {
-         *dbgout << json::object
-                     << "id"         << objectid(seg)
-                     << "passes"     << json::array;
-     }
- #endif
- 
--    bool res = aSilf->runGraphite(seg, 0, aSilf->justificationPass(), true);
-+//    if ((seg->dir() & 1) != aSilf->dir())
-+//        seg->reverseSlots();
-+    if ((seg->dir() & 3) == 3 && aSilf->bidiPass() == 0xFF)
-+        seg->doMirror(aSilf->aMirror());
-+    bool res = aSilf->runGraphite(seg, 0, aSilf->positionPass(), true);
-     if (res)
--        res = aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
-+    {
-+        seg->associateChars(0, seg->charInfoCount());
-+        if (aSilf->flags() & 0x20)
-+            res &= seg->initCollisions();
-+        res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
-+    }
- 
- #if !defined GRAPHITE2_NTRACING
-     if (dbgout)
- {
-+        seg->positionSlots(0, 0, 0, aSilf->dir());
-         *dbgout             << json::item
-                             << json::close // Close up the passes array
-                 << "output" << json::array;
-         for(Slot * s = seg->first(); s; s = s->next())
-             *dbgout     << dslot(seg, s);
--        seg->finalise(0);                   // Call this here to fix up charinfo back indexes.
-         *dbgout         << json::close
-                 << "advance" << seg->advance()
-                 << "chars"   << json::array;
-         for(size_t i = 0, n = seg->charInfoCount(); i != n; ++i)
-             *dbgout     << json::flat << *seg->charinfo(i);
-         *dbgout         << json::close  // Close up the chars array
-                     << json::close;     // Close up the segment object
-     }
-@@ -208,17 +232,19 @@ uint16 Face::findPseudo(uint32 uid) cons
- }
- 
- uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const
- {
-     switch (metrics(metric))
-     {
-         case kgmetAscent : return m_ascent;
-         case kgmetDescent : return m_descent;
--        default: return glyphs().glyph(gid)->getMetric(metric);
-+        default: 
-+            if (gid >= glyphs().numGlyphs()) return 0;
-+            return glyphs().glyph(gid)->getMetric(metric);
-     }
- }
- 
- void Face::takeFileFace(FileFace* pFileFace GR_MAYBE_UNUSED/*takes ownership*/)
- {
- #ifndef GRAPHITE2_NFILEFACE
-     if (m_pFileFace==pFileFace)
-       return;
-@@ -240,30 +266,100 @@ NameTable * Face::nameTable() const
- uint16 Face::languageForLocale(const char * locale) const
- {
-     nameTable();
-     if (m_pNames)
-         return m_pNames->getLanguageId(locale);
-     return 0;
- }
- 
--Face::Table::Table(const Face & face, const Tag n) throw()
--: _f(&face)
-+
-+
-+Face::Table::Table(const Face & face, const Tag n, uint32 version) throw()
-+: _f(&face), _compressed(false)
- {
-     size_t sz = 0;
--    _p = reinterpret_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &sz));
-+    _p = static_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &sz));
-     _sz = uint32(sz);
-+
-     if (!TtfUtil::CheckTable(n, _p, _sz))
-     {
-         this->~Table();     // Make sure we release the table buffer even if the table filed it's checks
--        _p = 0; _sz = 0;
-+        return;
-     }
-+
-+    if (be::peek<uint32>(_p) >= version)
-+        decompress();
-+}
-+
-+void Face::Table::releaseBuffers()
-+{
-+    if (_compressed)
-+        free(const_cast<byte *>(_p));
-+    else if (_p && _f->m_ops.release_table)
-+        (*_f->m_ops.release_table)(_f->m_appFaceHandle, _p);
-+    _p = 0; _sz = 0;
- }
- 
- Face::Table & Face::Table::operator = (const Table & rhs) throw()
- {
-     if (_p == rhs._p)   return *this;
- 
-     this->~Table();
-     new (this) Table(rhs);
-     return *this;
- }
- 
-+Error Face::Table::decompress()
-+{
-+    Error e;
-+    if (e.test(_sz < 5 * sizeof(uint32), E_BADSIZE))
-+        return e;
-+    byte * uncompressed_table = 0;
-+    size_t uncompressed_size = 0;
-+
-+    const byte * p = _p;
-+    const uint32 version = be::read<uint32>(p);    // Table version number.
-+
-+    // The scheme is in the top 5 bits of the 1st uint32.
-+    const uint32 hdr = be::read<uint32>(p);
-+    switch(compression(hdr >> 27))
-+    {
-+    case NONE: return e;
-+
-+    case LZ4:
-+    {
-+        uncompressed_size  = hdr & 0x07ffffff;
-+        uncompressed_table = gralloc<byte>(uncompressed_size);
-+        if (!e.test(!uncompressed_table, E_OUTOFMEM))
-+            // coverity[forward_null : FALSE] - uncompressed_table has been checked so can't be null
-+            // coverity[checked_return : FALSE] - we test e later
-+            e.test(lz4::decompress(p, _sz - 2*sizeof(uint32), uncompressed_table, uncompressed_size) != signed(uncompressed_size), E_SHRINKERFAILED);
-+        break;
-+    }
-+
-+    default:
-+        e.error(E_BADSCHEME);
-+    };
-+
-+    // Check the uncompressed version number against the original.
-+    if (!e)
-+        // coverity[forward_null : FALSE] - uncompressed_table has already been tested so can't be null
-+        // coverity[checked_return : FALSE] - we test e later
-+        e.test(be::peek<uint32>(uncompressed_table) != version, E_SHRINKERFAILED);
-+
-+    // Tell the provider to release the compressed form since were replacing
-+    //   it anyway.
-+    releaseBuffers();
-+
-+    if (e)
-+    {
-+        free(uncompressed_table);
-+        uncompressed_table = 0;
-+        uncompressed_size  = 0;
-+    }
-+
-+    _p = uncompressed_table;
-+    _sz = uncompressed_size;
-+    _compressed = true;
-+
-+    return e;
-+}
-diff --git a/gfx/graphite2/src/FeatureMap.cpp b/gfx/graphite2/src/FeatureMap.cpp
---- a/gfx/graphite2/src/FeatureMap.cpp
-+++ b/gfx/graphite2/src/FeatureMap.cpp
-@@ -126,60 +126,61 @@ bool FeatureMap::readFeats(const Face & 
-     unsigned short bits = 0;     //to cause overflow on first Feature
- 
-     for (int i = 0, ie = m_numFeats; i != ie; i++)
-     {
-         const uint32    label   = version < 0x00020000 ? be::read<uint16>(p) : be::read<uint32>(p);
-         const uint16    num_settings = be::read<uint16>(p);
-         if (version >= 0x00020000)
-             be::skip<uint16>(p);
--        const byte * const feat_setts = feat_start + be::read<uint32>(p);
-+        const uint32    settings_offset = be::read<uint32>(p);
-         const uint16    flags  = be::read<uint16>(p),
-                         uiName = be::read<uint16>(p);
- 
--        if (feat_setts + num_settings * FEATURE_SETTING_SIZE > feat_end)
-+        if (settings_offset > size_t(feat_end - feat_start) 
-+            || settings_offset + num_settings * FEATURE_SETTING_SIZE > size_t(feat_end - feat_start))
-         {
-             free(defVals);
-             return false;
-         }
- 
-         FeatureSetting *uiSet;
-         uint32 maxVal;
-         if (num_settings != 0)
-         {
-             uiSet = gralloc<FeatureSetting>(num_settings);
-             if (!uiSet)
-             {
-                 free(defVals);
-                 return false;
-             }
--            maxVal = readFeatureSettings(feat_setts, uiSet, num_settings);
-+            maxVal = readFeatureSettings(feat_start + settings_offset, uiSet, num_settings);
-             defVals[i] = uiSet[0].value();
-         }
-         else
-         {
-             uiSet = 0;
-             maxVal = 0xffffffff;
-             defVals[i] = 0;
-         }
- 
-         ::new (m_feats + i) FeatureRef (face, bits, maxVal,
-                                        label, uiName, flags,
-                                        uiSet, num_settings);
-     }
--    m_defaultFeatures = new Features(bits/(sizeof(uint32)*8) + 1, *this);
-+    new (&m_defaultFeatures) Features(bits/(sizeof(uint32)*8) + 1, *this);
-     m_pNamedFeats = new NameAndFeatureRef[m_numFeats];
--    if (!m_defaultFeatures || !m_pNamedFeats)
-+    if (!m_pNamedFeats)
-     {
-         free(defVals);
-         return false;
-     }
-     for (int i = 0; i < m_numFeats; ++i)
-     {
--        m_feats[i].applyValToFeature(defVals[i], *m_defaultFeatures);
-+        m_feats[i].applyValToFeature(defVals[i], m_defaultFeatures);
-         m_pNamedFeats[i] = m_feats+i;
-     }
-     
-     free(defVals);
- 
-     qsort(m_pNamedFeats, m_numFeats, sizeof(NameAndFeatureRef), &cmpNameAndFeatures);
- 
-     return true;
-@@ -209,17 +210,17 @@ bool SillMap::readSill(const Face & face
-     if (sill.size() < m_numLanguages * 8U + 12) return false;
- 
-     for (int i = 0; i < m_numLanguages; i++)
-     {
-         uint32 langid = be::read<uint32>(p);
-         uint16 numSettings = be::read<uint16>(p);
-         uint16 offset = be::read<uint16>(p);
-         if (offset + 8U * numSettings > sill.size() && numSettings > 0) return false;
--        Features* feats = new Features(*m_FeatureMap.m_defaultFeatures);
-+        Features* feats = new Features(m_FeatureMap.m_defaultFeatures);
-         if (!feats) return false;
-         const byte *pLSet = sill + offset;
- 
-         // Apply langauge specific settings
-         for (int j = 0; j < numSettings; j++)
-         {
-             uint32 name = be::read<uint32>(pLSet);
-             uint16 val = be::read<uint16>(pLSet);
-@@ -245,17 +246,17 @@ Features* SillMap::cloneFeatures(uint32 
-         // the number of languages in a font is usually small e.g. 8 in Doulos
-         // so this loop is not very expensive
-         for (uint16 i = 0; i < m_numLanguages; i++)
-         {
-             if (m_langFeats[i].m_lang == langname)
-                 return new Features(*m_langFeats[i].m_pFeatures);
-         }
-     }
--    return new Features (*m_FeatureMap.m_defaultFeatures);
-+    return new Features (m_FeatureMap.m_defaultFeatures);
- }
- 
- 
- 
- const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const
- {
-     NameAndFeatureRef *it;
-     
-diff --git a/gfx/graphite2/src/FileFace.cpp b/gfx/graphite2/src/FileFace.cpp
---- a/gfx/graphite2/src/FileFace.cpp
-+++ b/gfx/graphite2/src/FileFace.cpp
-@@ -55,18 +55,22 @@ FileFace::FileFace(const char *filename)
-         if (fread(_header_tbl, 1, tbl_len, _file) != tbl_len) return;
-         if (!TtfUtil::CheckHeader(_header_tbl)) return;
-     }
- 
-     // Get the table directory
-     if (!TtfUtil::GetTableDirInfo(_header_tbl, tbl_offset, tbl_len)) return;
-     _table_dir = (TtfUtil::Sfnt::OffsetSubTable::Entry*)gralloc<char>(tbl_len);
-     if (fseek(_file, tbl_offset, SEEK_SET)) return;
--    if (_table_dir)
--        if (fread(_table_dir, 1, tbl_len, _file) != tbl_len) return;
-+    if (_table_dir && fread(_table_dir, 1, tbl_len, _file) != tbl_len)
-+    {
-+        free(_table_dir);
-+        _table_dir = NULL;
-+    }
-+    return;
- }
- 
- FileFace::~FileFace()
- {
-     free(_table_dir);
-     free(_header_tbl);
-     if (_file)
-         fclose(_file);
-@@ -78,17 +82,17 @@ const void *FileFace::get_table_fn(const
-     if (appFaceHandle == 0)     return 0;
-     const FileFace & file_face = *static_cast<const FileFace *>(appFaceHandle);
- 
-     void *tbl;
-     size_t tbl_offset, tbl_len;
-     if (!TtfUtil::GetTableInfo(name, file_face._header_tbl, file_face._table_dir, tbl_offset, tbl_len))
-         return 0;
- 
--    if (tbl_offset + tbl_len > file_face._file_len
-+    if (tbl_offset > file_face._file_len || tbl_len > file_face._file_len - tbl_offset
-             || fseek(file_face._file, tbl_offset, SEEK_SET) != 0)
-         return 0;
- 
-     tbl = malloc(tbl_len);
-     if (fread(tbl, 1, tbl_len, file_face._file) != tbl_len)
-     {
-         free(tbl);
-         return 0;
-diff --git a/gfx/graphite2/src/GlyphCache.cpp b/gfx/graphite2/src/GlyphCache.cpp
---- a/gfx/graphite2/src/GlyphCache.cpp
-+++ b/gfx/graphite2/src/GlyphCache.cpp
-@@ -26,16 +26,17 @@ of the License or (at your option) any l
- */
- #include "graphite2/Font.h"
- 
- #include "inc/Main.h"
- #include "inc/Face.h"     //for the tags
- #include "inc/GlyphCache.h"
- #include "inc/GlyphFace.h"
- #include "inc/Endian.h"
-+#include "inc/bits.h"
- 
- using namespace graphite2;
- 
- namespace
- {
-     // Iterator over version 1 or 2 glat entries which consist of a series of
-     //    +-+-+-+-+-+-+-+-+-+-+                +-+-+-+-+-+-+-+-+-+-+-+-+
-     // v1 |k|n|v1 |v2 |...|vN |     or    v2   | k | n |v1 |v2 |...|vN |
-@@ -56,99 +57,127 @@ namespace
-             if (_n == run()) advance_entry();
-             return *this;
-         }
-         _glat_iterator<W>   operator ++ (int)   { _glat_iterator<W> tmp(*this); operator++(); return tmp; }
- 
-         // This is strictly a >= operator. A true == operator could be
-         // implemented that test for overlap but it would be more expensive a
-         // test.
--        bool operator == (const _glat_iterator<W> & rhs) { return _v >= rhs._e; }
-+        bool operator == (const _glat_iterator<W> & rhs) { return _v >= rhs._e - 1; }
-         bool operator != (const _glat_iterator<W> & rhs) { return !operator==(rhs); }
- 
-         value_type          operator * () const {
-             return value_type(key(), be::peek<uint16>(_v));
-         }
- 
-     protected:
-         const byte     * _e, * _v;
--        ptrdiff_t        _n;
-+        size_t        _n;
-     };
- 
-     typedef _glat_iterator<uint8>   glat_iterator;
-     typedef _glat_iterator<uint16>  glat2_iterator;
- }
- 
-+const SlantBox SlantBox::empty = {0,0,0,0};
-+
- 
- class GlyphCache::Loader
- {
- public:
-     Loader(const Face & face, const bool dumb_font);    //return result indicates success. Do not use if failed.
- 
-     operator bool () const throw();
-     unsigned short int units_per_em() const throw();
-     unsigned short int num_glyphs() const throw();
-     unsigned short int num_attrs() const throw();
-+    bool has_boxes() const throw();
- 
--    const GlyphFace * read_glyph(unsigned short gid, GlyphFace &) const throw();
-+    const GlyphFace * read_glyph(unsigned short gid, GlyphFace &, int *numsubs) const throw();
-+    GlyphBox * read_box(uint16 gid, GlyphBox *curr, const GlyphFace & face) const throw();
- 
-     CLASS_NEW_DELETE;
- private:
-     Face::Table _head,
-                 _hhea,
-                 _hmtx,
-                 _glyf,
-                 _loca,
-                 m_pGlat,
-                 m_pGloc;
- 
-     bool            _long_fmt;
-+    bool            _has_boxes;
-     unsigned short  _num_glyphs_graphics,        //i.e. boundary box and advance
-                     _num_glyphs_attributes,
-                     _num_attrs;                    // number of glyph attributes per glyph
- };
- 
- 
- 
- GlyphCache::GlyphCache(const Face & face, const uint32 face_options)
- : _glyph_loader(new Loader(face, bool(face_options & gr_face_dumbRendering))),
-   _glyphs(_glyph_loader && *_glyph_loader ? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0),
-+  _boxes(_glyph_loader && _glyph_loader->has_boxes() ? grzeroalloc<GlyphBox *>(_glyph_loader->num_glyphs()) : 0),
-   _num_glyphs(_glyphs ? _glyph_loader->num_glyphs() : 0),
-   _num_attrs(_glyphs ? _glyph_loader->num_attrs() : 0),
-   _upem(_glyphs ? _glyph_loader->units_per_em() : 0)
- {
-     if ((face_options & gr_face_preloadGlyphs) && _glyph_loader && _glyphs)
-     {
-+        int numsubs = 0;
-         GlyphFace * const glyphs = new GlyphFace [_num_glyphs];
-         if (!glyphs)
-             return;
- 
-         // The 0 glyph is definately required.
--        _glyphs[0] = _glyph_loader->read_glyph(0, glyphs[0]);
-+        _glyphs[0] = _glyph_loader->read_glyph(0, glyphs[0], &numsubs);
- 
-         // glyphs[0] has the same address as the glyphs array just allocated,
-         //  thus assigning the &glyphs[0] to _glyphs[0] means _glyphs[0] points
-         //  to the entire array.
-         const GlyphFace * loaded = _glyphs[0];
-         for (uint16 gid = 1; loaded && gid != _num_glyphs; ++gid)
--            _glyphs[gid] = loaded = _glyph_loader->read_glyph(gid, glyphs[gid]);
-+            _glyphs[gid] = loaded = _glyph_loader->read_glyph(gid, glyphs[gid], &numsubs);
- 
-         if (!loaded)
-         {
-             _glyphs[0] = 0;
-             delete [] glyphs;
-         }
-+        else if (numsubs > 0)
-+        {
-+            GlyphBox * boxes = (GlyphBox *)gralloc<char>(_num_glyphs * sizeof(GlyphBox) + numsubs * 8 * sizeof(float));
-+            GlyphBox * currbox = boxes;
-+
-+            for (uint16 gid = 0; currbox && gid != _num_glyphs; ++gid)
-+            {
-+                _boxes[gid] = currbox;
-+                currbox = _glyph_loader->read_box(gid, currbox, *_glyphs[gid]);
-+            }
-+            if (!currbox)
-+            {
-+                free(boxes);
-+                _boxes[0] = 0;
-+            }
-+        }
-         delete _glyph_loader;
-         _glyph_loader = 0;
-     }
- 
-     if (_glyphs && glyph(0) == 0)
-     {
-         free(_glyphs);
-         _glyphs = 0;
-+        if (_boxes)
-+        {
-+            free(_boxes);
-+            _boxes = 0;
-+        }
-         _num_glyphs = _num_attrs = _upem = 0;
-     }
- }
- 
- 
- GlyphCache::~GlyphCache()
- {
-     if (_glyphs)
-@@ -158,91 +187,130 @@ GlyphCache::~GlyphCache()
-             const GlyphFace *  * g = _glyphs;
-             for(unsigned short n = _num_glyphs; n; --n, ++g)
-                 delete *g;
-         }
-         else
-             delete [] _glyphs[0];
-         free(_glyphs);
-     }
-+    if (_boxes)
-+    {
-+        if (_glyph_loader)
-+        {
-+            GlyphBox *  * g = _boxes;
-+            for (uint16 n = _num_glyphs; n; --n, ++g)
-+                free(*g);
-+        }
-+        else
-+            free(_boxes[0]);
-+        free(_boxes);
-+    }
-     delete _glyph_loader;
- }
- 
- const GlyphFace *GlyphCache::glyph(unsigned short glyphid) const      //result may be changed by subsequent call with a different glyphid
- { 
-     const GlyphFace * & p = _glyphs[glyphid];
-     if (p == 0 && _glyph_loader)
-     {
-+        int numsubs = 0;
-         GlyphFace * g = new GlyphFace();
--        if (g)  p = _glyph_loader->read_glyph(glyphid, *g);
-+        if (g)  p = _glyph_loader->read_glyph(glyphid, *g, &numsubs);
-         if (!p)
-         {
-             delete g;
-             return *_glyphs;
-         }
-+        if (_boxes)
-+        {
-+            _boxes[glyphid] = (GlyphBox *)gralloc<char>(sizeof(GlyphBox) + 8 * numsubs * sizeof(float));
-+            if (!_glyph_loader->read_box(glyphid, _boxes[glyphid], *_glyphs[glyphid]))
-+            {
-+                free(_boxes[glyphid]);
-+                _boxes[glyphid] = 0;
-+            }
-+        }
-     }
-     return p;
- }
- 
- 
- 
- GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
- : _head(face, Tag::head),
-   _hhea(face, Tag::hhea),
-   _hmtx(face, Tag::hmtx),
-   _glyf(face, Tag::glyf),
-   _loca(face, Tag::loca),
-   _long_fmt(false),
-+  _has_boxes(false),
-   _num_glyphs_graphics(0),
-   _num_glyphs_attributes(0),
-   _num_attrs(0)
- {
-     if (!operator bool())
-         return;
- 
-     const Face::Table maxp = Face::Table(face, Tag::maxp);
-     if (!maxp) { _head = Face::Table(); return; }
- 
-     _num_glyphs_graphics = TtfUtil::GlyphCount(maxp);
-     // This will fail if the number of glyphs is wildly out of range.
--    if (_glyf && TtfUtil::LocaLookup(_num_glyphs_graphics-1, _loca, _loca.size(), _head) == size_t(-1))
-+    if (_glyf && TtfUtil::LocaLookup(_num_glyphs_graphics-1, _loca, _loca.size(), _head) == size_t(-2))
-     {
-         _head = Face::Table();
-         return;
-     }
- 
-     if (!dumb_font)
-     {
--        if ((m_pGlat = Face::Table(face, Tag::Glat)) == NULL
-+        if ((m_pGlat = Face::Table(face, Tag::Glat, 0x00030000)) == NULL
-             || (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
-             || m_pGloc.size() < 6)
-         {
-             _head = Face::Table();
-             return;
-         }
-         const byte    * p = m_pGloc;
--        const int       version = be::read<uint32>(p);
-+        int       version = be::read<uint32>(p);
-         const uint16    flags = be::read<uint16>(p);
-         _num_attrs = be::read<uint16>(p);
-         // We can accurately calculate the number of attributed glyphs by
-         //  subtracting the length of the attribids array (numAttribs long if present)
-         //  and dividing by either 2 or 4 depending on shor or lonf format
-         _long_fmt              = flags & 1;
--        _num_glyphs_attributes = (m_pGloc.size()
-+        int tmpnumgattrs       = (m_pGloc.size()
-                                    - (p - m_pGloc)
-                                    - sizeof(uint16)*(flags & 0x2 ? _num_attrs : 0))
-                                        / (_long_fmt ? sizeof(uint32) : sizeof(uint16)) - 1;
- 
--        if (version != 0x00010000
-+        if (version >= 0x00020000 || tmpnumgattrs < 0 || tmpnumgattrs > 65535
-             || _num_attrs == 0 || _num_attrs > 0x3000  // is this hard limit appropriate?
--            || _num_glyphs_graphics > _num_glyphs_attributes)
-+            || _num_glyphs_graphics > tmpnumgattrs)
-         {
-             _head = Face::Table();
-             return;
-         }
-+
-+        _num_glyphs_attributes = static_cast<unsigned short>(tmpnumgattrs);
-+        p = m_pGlat;
-+        version = be::read<uint32>(p);
-+        if (version >= 0x00040000)       // reject Glat tables that are too new
-+        {
-+            _head = Face::Table();
-+            return;
-+        }
-+        else if (version >= 0x00030000)
-+        {
-+            unsigned int glatflags = be::read<uint32>(p);
-+            _has_boxes = glatflags & 1;
-+            // delete this once the compiler is fixed
-+            _has_boxes = true;
-+        }
-     }
- }
- 
- inline
- GlyphCache::Loader::operator bool () const throw()
- {
-     return _head && _hhea && _hmtx && !(bool(_glyf) != bool(_loca));
- }
-@@ -260,34 +328,44 @@ unsigned short int GlyphCache::Loader::n
- }
- 
- inline
- unsigned short int GlyphCache::Loader::num_attrs() const throw()
- {
-     return _num_attrs;
- }
- 
--const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFace & glyph) const throw()
-+inline
-+bool GlyphCache::Loader::has_boxes () const throw()
-+{
-+    return _has_boxes;
-+}
-+
-+const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFace & glyph, int *numsubs) const throw()
- {
-     Rect        bbox;
-     Position    advance;
- 
-     if (glyphid < _num_glyphs_graphics)
-     {
-         int nLsb;
-         unsigned int nAdvWid;
-         if (_glyf)
-         {
-             int xMin, yMin, xMax, yMax;
-             size_t locidx = TtfUtil::LocaLookup(glyphid, _loca, _loca.size(), _head);
-             void *pGlyph = TtfUtil::GlyfLookup(_glyf, locidx, _glyf.size());
- 
-             if (pGlyph && TtfUtil::GlyfBox(pGlyph, xMin, yMin, xMax, yMax))
-+            {
-+                if ((xMin > xMax) || (yMin > yMax))
-+                    return 0;
-                 bbox = Rect(Position(static_cast<float>(xMin), static_cast<float>(yMin)),
-                     Position(static_cast<float>(xMax), static_cast<float>(yMax)));
-+            }
-         }
-         if (TtfUtil::HorMetrics(glyphid, _hmtx, _hmtx.size(), _hhea, nLsb, nAdvWid))
-             advance = Position(static_cast<float>(nAdvWid), 0);
-     }
- 
-     if (glyphid < _num_glyphs_attributes)
-     {
-         const byte * gloc = m_pGloc;
-@@ -307,35 +385,95 @@ const GlyphFace * GlyphCache::Loader::re
-             glocs = be::read<uint16>(gloc);
-             gloce = be::peek<uint16>(gloc);
-         }
- 
-         if (glocs >= m_pGlat.size() || gloce > m_pGlat.size())
-             return 0;
- 
-         const uint32 glat_version = be::peek<uint32>(m_pGlat);
-+        if (glat_version == 0x00030000)
-+        {
-+            const byte * p = m_pGlat + glocs;
-+            uint16 bmap = be::read<uint16>(p);
-+            int num = bit_set_count((uint32)bmap);
-+            if (numsubs) *numsubs += num;
-+            glocs += 6 + 8 * num;
-+            if (glocs > gloce)
-+                return 0;
-+        }
-         if (glat_version < 0x00020000)
-         {
-             if (gloce - glocs < 2*sizeof(byte)+sizeof(uint16)
-                 || gloce - glocs > _num_attrs*(2*sizeof(byte)+sizeof(uint16)))
--            {
--                return 0;
--            }
--
-+                    return 0;
-             new (&glyph) GlyphFace(bbox, advance, glat_iterator(m_pGlat + glocs), glat_iterator(m_pGlat + gloce));
-         }
-         else
-         {
--            if (gloce - glocs < 3*sizeof(uint16)
--                || gloce - glocs > _num_attrs*3*sizeof(uint16))
--            {
--                return 0;
--            }
--
-+            if (gloce - glocs < 3*sizeof(uint16)        // can a glyph have no attributes? why not?
-+                || gloce - glocs > _num_attrs*3*sizeof(uint16)
-+                || glocs > m_pGlat.size() - 2*sizeof(uint16))
-+                    return 0;
-             new (&glyph) GlyphFace(bbox, advance, glat2_iterator(m_pGlat + glocs), glat2_iterator(m_pGlat + gloce));
-         }
--
-         if (!glyph.attrs() || glyph.attrs().capacity() > _num_attrs)
-             return 0;
-     }
--
-     return &glyph;
- }
-+
-+inline float scale_to(uint8 t, float zmin, float zmax)
-+{
-+    return (zmin + t * (zmax - zmin) / 255);
-+}
-+
-+Rect readbox(Rect &b, uint8 zxmin, uint8 zymin, uint8 zxmax, uint8 zymax)
-+{
-+    return Rect(Position(scale_to(zxmin, b.bl.x, b.tr.x), scale_to(zymin, b.bl.y, b.tr.y)),
-+                Position(scale_to(zxmax, b.bl.x, b.tr.x), scale_to(zymax, b.bl.y, b.tr.y)));
-+}
-+
-+GlyphBox * GlyphCache::Loader::read_box(uint16 gid, GlyphBox *curr, const GlyphFace & glyph) const throw()
-+{
-+    if (gid >= _num_glyphs_attributes) return 0;
-+
-+    const byte * gloc = m_pGloc;
-+    size_t      glocs = 0, gloce = 0;
-+
-+    be::skip<uint32>(gloc);
-+    be::skip<uint16>(gloc,2);
-+    if (_long_fmt)
-+    {
-+        be::skip<uint32>(gloc, gid);
-+        glocs = be::read<uint32>(gloc);
-+        gloce = be::peek<uint32>(gloc);
-+    }
-+    else
-+    {
-+        be::skip<uint16>(gloc, gid);
-+        glocs = be::read<uint16>(gloc);
-+        gloce = be::peek<uint16>(gloc);
-+    }
-+
-+    if (glocs >= m_pGlat.size() || gloce > m_pGlat.size())
-+        return 0;
-+
-+    const byte * p = m_pGlat + glocs;
-+    uint16 bmap = be::read<uint16>(p);
-+    int num = bit_set_count((uint32)bmap);
-+
-+    Rect bbox = glyph.theBBox();
-+    Rect diamax(Position(bbox.bl.x + bbox.bl.y, bbox.bl.x - bbox.tr.y),
-+                Position(bbox.tr.x + bbox.tr.y, bbox.tr.x - bbox.bl.y));
-+    Rect diabound = readbox(diamax, p[0], p[2], p[1], p[3]);
-+    ::new (curr) GlyphBox(num, bmap, &diabound);
-+    be::skip<uint8>(p, 4);
-+
-+    for (int i = 0; i < num * 2; ++i)
-+    {
-+        Rect box = readbox((i & 1) ? diamax : bbox, p[0], p[2], p[1], p[3]);
-+        curr->addSubBox(i >> 1, i & 1, &box);
-+        be::skip<uint8>(p, 4);
-+    } 
-+    return (GlyphBox *)((char *)(curr) + sizeof(GlyphBox) + 2 * num * sizeof(Rect));
-+}
-+
-diff --git a/gfx/graphite2/src/Intervals.cpp b/gfx/graphite2/src/Intervals.cpp
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/Intervals.cpp
-@@ -0,0 +1,294 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2010, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+#include <algorithm>
-+#include <cmath>
-+#include <limits>
-+
-+#include "inc/Intervals.h"
-+#include "inc/Segment.h"
-+#include "inc/Slot.h"
-+#include "inc/debug.h"
-+#include "inc/bits.h"
-+
-+using namespace graphite2;
-+
-+#include <cmath>
-+
-+inline
-+Zones::Exclusion  Zones::Exclusion::split_at(float p) {
-+    Exclusion r(*this);
-+    r.xm = x = p;
-+    return r;
-+}
-+
-+inline
-+void Zones::Exclusion::left_trim(float p) {
-+    x = p;
-+}
-+
-+inline
-+Zones::Exclusion & Zones::Exclusion::operator += (Exclusion const & rhs) {
-+    c += rhs.c; sm += rhs.sm; smx += rhs.smx; open = false;
-+    return *this;
-+}
-+
-+inline
-+uint8 Zones::Exclusion::outcode(float val) const {
-+    float p = val;
-+    return ((p >= xm) << 1) | (p < x);
-+}
-+
-+void Zones::exclude_with_margins(float xmin, float xmax, int axis) {
-+    remove(xmin, xmax);
-+    weightedAxis(axis, xmin-_margin_len, xmin, 0, 0, _margin_weight, xmin-_margin_len, 0, 0, false);
-+    weightedAxis(axis, xmax, xmax+_margin_len, 0, 0, _margin_weight, xmax+_margin_len, 0, 0, false);
-+}
-+
-+namespace
-+{
-+
-+inline
-+bool separated(float a, float b) {
-+    return a != b;
-+    //return std::fabs(a-b) > std::numeric_limits<float>::epsilon(); // std::epsilon may not work. but 0.5 fails exising 64 bit tests
-+    //return std::fabs(a-b) > 0.5f;
-+}
-+
-+}
-+
-+void Zones::insert(Exclusion e)
-+{
-+#if !defined GRAPHITE2_NTRACING
-+    addDebug(&e);
-+#endif
-+    e.x = max(e.x, _pos);
-+    e.xm = min(e.xm, _posm);
-+    if (e.x >= e.xm) return;
-+
-+    for (iterator i = _exclusions.begin(), ie = _exclusions.end(); i != ie && e.x < e.xm; ++i)
-+    {
-+        const uint8 oca = e.outcode(i->x),
-+                    ocb = e.outcode(i->xm);
-+        if ((oca & ocb) != 0) continue;
-+
-+        switch (oca ^ ocb)  // What kind of overlap?
-+        {
-+        case 0:     // e completely covers i
-+            // split e at i.x into e1,e2
-+            // split e2 at i.mx into e2,e3
-+            // drop e1 ,i+e2, e=e3
-+            *i += e;
-+            e.left_trim(i->xm);
-+            break;
-+        case 1:     // e overlaps on the rhs of i
-+            // split i at e->x into i1,i2
-+            // split e at i.mx into e1,e2
-+            // trim i1, insert i2+e1, e=e2
-+            if (!separated(i->xm, e.x)) break;
-+            if (separated(i->x,e.x))   { i = _exclusions.insert(i,i->split_at(e.x)); ++i; }
-+            *i += e;
-+            e.left_trim(i->xm);
-+            break;
-+        case 2:     // e overlaps on the lhs of i
-+            // split e at i->x into e1,e2
-+            // split i at e.mx into i1,i2
-+            // drop e1, insert e2+i1, trim i2
-+            if (!separated(e.xm, i->x)) return;
-+            if (separated(e.xm, i->xm)) i = _exclusions.insert(i,i->split_at(e.xm));
-+            *i += e;
-+            return;
-+        case 3:     // i completely covers e
-+            // split i at e.x into i1,i2
-+            // split i2 at e.mx into i2,i3
-+            // insert i1, insert e+i2
-+            if (separated(e.xm, i->xm)) i = _exclusions.insert(i,i->split_at(e.xm));
-+            i = _exclusions.insert(i, i->split_at(e.x));
-+            *++i += e;
-+            return;
-+        }
-+
-+        ie = _exclusions.end();
-+    }
-+}
-+
-+
-+void Zones::remove(float x, float xm)
-+{
-+#if !defined GRAPHITE2_NTRACING
-+    removeDebug(x, xm);
-+#endif
-+    x = max(x, _pos);
-+    xm = min(xm, _posm);
-+    if (x >= xm) return;
-+
-+    for (iterator i = _exclusions.begin(), ie = _exclusions.end(); i != ie; ++i)
-+    {
-+        const uint8 oca = i->outcode(x),
-+                    ocb = i->outcode(xm);
-+        if ((oca & ocb) != 0)   continue;
-+
-+        switch (oca ^ ocb)  // What kind of overlap?
-+        {
-+        case 0:     // i completely covers e
-+            if (separated(i->x, x))  { i = _exclusions.insert(i,i->split_at(x)); ++i; }
-+            GR_FALLTHROUGH;
-+            // no break
-+        case 1:     // i overlaps on the rhs of e
-+            i->left_trim(xm);
-+            return;
-+        case 2:     // i overlaps on the lhs of e
-+            i->xm = x;
-+            if (separated(i->x, i->xm)) break;
-+            GR_FALLTHROUGH;
-+            // no break
-+        case 3:     // e completely covers i
-+            i = _exclusions.erase(i);
-+            --i;
-+            break;
-+        }
-+
-+        ie = _exclusions.end();
-+    }
-+}
-+
-+
-+Zones::const_iterator Zones::find_exclusion_under(float x) const
-+{
-+    int l = 0, h = _exclusions.size();
-+
-+    while (l < h)
-+    {
-+        int const p = (l+h) >> 1;
-+        switch (_exclusions[p].outcode(x))
-+        {
-+        case 0 : return _exclusions.begin()+p;
-+        case 1 : h = p; break;
-+        case 2 : 
-+        case 3 : l = p+1; break;
-+        }
-+    }
-+
-+    return _exclusions.begin()+l;
-+}
-+
-+
-+float Zones::closest(float origin, float & cost) const
-+{
-+    float best_c = std::numeric_limits<float>::max(),
-+          best_x = 0;
-+
-+    const const_iterator start = find_exclusion_under(origin);
-+
-+    // Forward scan looking for lowest cost
-+    for (const_iterator i = start, ie = _exclusions.end(); i != ie; ++i)
-+        if (i->track_cost(best_c, best_x, origin)) break;
-+
-+    // Backward scan looking for lowest cost
-+    //  We start from the exclusion to the immediate left of start since we've
-+    //  already tested start with the right most scan above.
-+    for (const_iterator i = start-1, ie = _exclusions.begin()-1; i != ie; --i)
-+        if (i->track_cost(best_c, best_x, origin)) break;
-+
-+    cost = (best_c == std::numeric_limits<float>::max() ? -1 : best_c);
-+    return best_x;
-+}
-+
-+
-+// Cost and test position functions
-+
-+bool Zones::Exclusion::track_cost(float & best_cost, float & best_pos, float origin) const {
-+    const float p = test_position(origin),
-+                localc = cost(p - origin);
-+    if (open && localc > best_cost) return true;
-+
-+    if (localc < best_cost)
-+    {
-+        best_cost = localc;
-+        best_pos = p;
-+    }
-+    return false;
-+}
-+
-+inline
-+float Zones::Exclusion::cost(float p) const {
-+    return (sm * p - 2 * smx) * p + c;
-+}
-+
-+
-+float Zones::Exclusion::test_position(float origin) const {
-+    if (sm < 0)
-+    {
-+        // sigh, test both ends and perhaps the middle too!
-+        float res = x;
-+        float cl = cost(x);
-+        if (x < origin && xm > origin)
-+        {
-+            float co = cost(origin);
-+            if (co < cl)
-+            {
-+                cl = co;
-+                res = origin;
-+            }
-+        }
-+        float cr = cost(xm);
-+        return cl > cr ? xm : res;
-+    }
-+    else
-+    {
-+        float zerox = smx / sm + origin;
-+        if (zerox < x) return x;
-+        else if (zerox > xm) return xm;
-+        else return zerox;
-+    }
-+}
-+
-+
-+#if !defined GRAPHITE2_NTRACING
-+
-+void Zones::jsonDbgOut(Segment *seg) const {
-+
-+    if (_dbg)
-+    {
-+        for (Zones::idebugs s = dbgs_begin(), e = dbgs_end(); s != e; ++s)
-+        {
-+            *_dbg << json::flat << json::array
-+                << objectid(dslot(seg, (Slot *)(s->_env[0])))
-+                << reinterpret_cast<ptrdiff_t>(s->_env[1]);
-+            if (s->_isdel)
-+                *_dbg << "remove" << Position(s->_excl.x, s->_excl.xm);
-+            else
-+                *_dbg << "exclude" << json::flat << json::array
-+                    << s->_excl.x << s->_excl.xm 
-+                    << s->_excl.sm << s->_excl.smx << s->_excl.c
-+                    << json::close;
-+            *_dbg << json::close;
-+        }
-+    }
-+}
-+
-+#endif
-+
-diff --git a/gfx/graphite2/src/Justifier.cpp b/gfx/graphite2/src/Justifier.cpp
---- a/gfx/graphite2/src/Justifier.cpp
-+++ b/gfx/graphite2/src/Justifier.cpp
-@@ -26,17 +26,17 @@ of the License or (at your option) any l
- */
- 
- #include "inc/Segment.h"
- #include "graphite2/Font.h"
- #include "inc/debug.h"
- #include "inc/CharInfo.h"
- #include "inc/Slot.h"
- #include "inc/Main.h"
--#include <math.h>
-+#include <cmath>
- 
- using namespace graphite2;
- 
- class JustifyTotal {
- public:
-     JustifyTotal() : m_numGlyphs(0), m_tStretch(0), m_tShrink(0), m_tStep(0), m_tWeight(0) {}
-     void accumulate(Slot *s, Segment *seg, int level);
-     int weight() const { return m_tWeight; }
-@@ -55,37 +55,44 @@ void JustifyTotal::accumulate(Slot *s, S
- {
-     ++m_numGlyphs;
-     m_tStretch += s->getJustify(seg, level, 0);
-     m_tShrink += s->getJustify(seg, level, 1);
-     m_tStep += s->getJustify(seg, level, 2);
-     m_tWeight += s->getJustify(seg, level, 3);
- }
- 
--float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags flags, Slot *pFirst, Slot *pLast)
-+float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags jflags, Slot *pFirst, Slot *pLast)
- {
-     Slot *s, *end;
-     float currWidth = 0.0;
-     const float scale = font ? font->scale() : 1.0f;
-     Position res;
- 
-     if (width < 0 && !(silf()->flags()))
-         return width;
- 
-+    if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
-+    {
-+        reverseSlots();
-+        s = pFirst;
-+        pFirst = pLast;
-+        pLast = s;
-+    }
-     if (!pFirst) pFirst = pSlot;
-     while (!pFirst->isBase()) pFirst = pFirst->attachedTo();
-     if (!pLast) pLast = last();
-     while (!pLast->isBase()) pLast = pLast->attachedTo();
-     const float base = pFirst->origin().x / scale;
-     width = width / scale;
--    if ((flags & gr_justEndInline) == 0)
-+    if ((jflags & gr_justEndInline) == 0)
-     {
-         do {
-             Rect bbox = theGlyphBBoxTemporary(pLast->glyph());
--            if (bbox.bl.x != 0. || bbox.bl.y != 0. || bbox.tr.x != 0. || bbox.tr.y == 0.)
-+            if (bbox.bl.x != 0.f || bbox.bl.y != 0.f || bbox.tr.x != 0.f || bbox.tr.y == 0.f)
-                 break;
-             pLast = pLast->prev();
-         } while (pLast != pFirst);
-     }
- 
-     end = pLast->nextSibling();
-     pFirst = pFirst->nextSibling();
- 
-@@ -111,28 +118,27 @@ float Segment::justify(Slot *pSlot, cons
-                 s->setJustify(this, 0, 3, 1);
-                 s->setJustify(this, 0, 2, 1);
-                 s->setJustify(this, 0, 0, -1);
-             }
-         }
-         ++numLevels;
-     }
- 
--    JustifyTotal *stats = new JustifyTotal[numLevels];
--    if (!stats) return -1.0;
-+    Vector<JustifyTotal> stats(numLevels);
-     for (s = pFirst; s != end; s = s->nextSibling())
-     {
-         float w = s->origin().x / scale + s->advance() - base;
-         if (w > currWidth) currWidth = w;
-         for (int j = 0; j < numLevels; ++j)
-             stats[j].accumulate(s, this, j);
-         s->just(0);
-     }
- 
--    for (int i = (width < 0.0) ? -1 : numLevels - 1; i >= 0; --i)
-+    for (int i = (width < 0.0f) ? -1 : numLevels - 1; i >= 0; --i)
-     {
-         float diff;
-         float error = 0.;
-         float diffpw;
-         int tWeight = stats[i].weight();
- 
-         do {
-             error = 0.;
-@@ -154,29 +160,29 @@ float Segment::justify(Slot *pSlot, cons
-                 }
-                 else
-                 {
-                     float max = uint16(s->getJustify(this, i, 1));
-                     if (i == 0) max += s->just();
-                     if (-pref > max) pref = -max;
-                     else tWeight += w;
-                 }
--                int actual = step ? int(pref / step) * step : int(pref);
-+                int actual = int(pref / step) * step;
- 
-                 if (actual)
-                 {
-                     error += diffpw * w - actual;
-                     if (i == 0)
-                         s->just(s->just() + actual);
-                     else
-                         s->setJustify(this, i, 4, actual);
-                 }
-             }
-             currWidth += diff - error;
--        } while (i == 0 && int(abs(error)) > 0 && tWeight);
-+        } while (i == 0 && int(std::abs(error)) > 0 && tWeight);
-     }
- 
-     Slot *oldFirst = m_first;
-     Slot *oldLast = m_last;
-     if (silf()->flags() & 1)
-     {
-         m_first = pSlot = addLineEnd(pSlot);
-         m_last = pLast = addLineEnd(end);
-@@ -192,41 +198,44 @@ float Segment::justify(Slot *pSlot, cons
- #if !defined GRAPHITE2_NTRACING
-     json * const dbgout = m_face->logger();
-     if (dbgout)
-         *dbgout << json::object
-                     << "justifies"  << objectid(this)
-                     << "passes"     << json::array;
- #endif
- 
--    if (m_silf->justificationPass() != m_silf->positionPass() && (width >= 0. || (silf()->flags() & 1)))
-+    if (m_silf->justificationPass() != m_silf->positionPass() && (width >= 0.f || (silf()->flags() & 1)))
-         m_silf->runGraphite(this, m_silf->justificationPass(), m_silf->positionPass());
- 
- #if !defined GRAPHITE2_NTRACING
-     if (dbgout)
-     {
-         *dbgout     << json::item << json::close; // Close up the passes array
--        positionSlots(NULL, pSlot, pLast);
-+        positionSlots(NULL, pSlot, pLast, m_dir);
-         Slot *lEnd = pLast->nextSibling();
-         *dbgout << "output" << json::array;
-         for(Slot * t = pSlot; t != lEnd; t = t->next())
-             *dbgout     << dslot(this, t);
-         *dbgout         << json::close << json::close;
-     }
- #endif
- 
--    res = positionSlots(font, pSlot, pLast);
-+    res = positionSlots(font, pSlot, pLast, m_dir);
- 
-     if (silf()->flags() & 1)
-     {
-         delLineEnd(m_first);
-         delLineEnd(m_last);
-     }
-     m_first = oldFirst;
-     m_last = oldLast;
-+
-+    if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
-+        reverseSlots();
-     return res.x;
- }
- 
- Slot *Segment::addLineEnd(Slot *nSlot)
- {
-     Slot *eSlot = newSlot();
-     if (!eSlot) return NULL;
-     const uint16 gid = silf()->endLineGlyphid();
-diff --git a/gfx/graphite2/src/Pass.cpp b/gfx/graphite2/src/Pass.cpp
---- a/gfx/graphite2/src/Pass.cpp
-+++ b/gfx/graphite2/src/Pass.cpp
-@@ -26,91 +26,120 @@ of the License or (at your option) any l
- */
- #include "inc/Main.h"
- #include "inc/debug.h"
- #include "inc/Endian.h"
- #include "inc/Pass.h"
- #include <cstring>
- #include <cstdlib>
- #include <cassert>
-+#include <cmath>
- #include "inc/Segment.h"
- #include "inc/Code.h"
- #include "inc/Rule.h"
- #include "inc/Error.h"
-+#include "inc/Collider.h"
- 
- using namespace graphite2;
- using vm::Machine;
- typedef Machine::Code  Code;
- 
-+enum KernCollison
-+{
-+    None       = 0,
-+    CrossSpace = 1,
-+    InWord     = 2,
-+    reserved   = 3
-+};
- 
- Pass::Pass()
- : m_silf(0),
-   m_cols(0),
-   m_rules(0),
-   m_ruleMap(0),
-   m_startStates(0),
-   m_transitions(0),
-   m_states(0),
--  m_flags(0),
-+  m_codes(0),
-+  m_progs(0),
-+  m_numCollRuns(0),
-+  m_kernColls(0),
-   m_iMaxLoop(0),
-   m_numGlyphs(0),
-   m_numRules(0),
-   m_numStates(0),
-   m_numTransition(0),
-   m_numSuccess(0),
-+  m_successStart(0),
-   m_numColumns(0),
-   m_minPreCtxt(0),
--  m_maxPreCtxt(0)
-+  m_maxPreCtxt(0),
-+  m_colThreshold(0),
-+  m_isReverseDir(false)
- {
- }
- 
- Pass::~Pass()
- {
-     free(m_cols);
-     free(m_startStates);
-     free(m_transitions);
-     free(m_states);
-     free(m_ruleMap);
- 
--    delete [] m_rules;
-+    if (m_rules) delete [] m_rules;
-+    if (m_codes) delete [] m_codes;
-+    free(m_progs);
- }
- 
--bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t subtable_base, GR_MAYBE_UNUSED Face & face, Error &e)
-+bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t subtable_base,
-+        GR_MAYBE_UNUSED Face & face, passtype pt, GR_MAYBE_UNUSED uint32 version, Error &e)
- {
--    const byte *                p = pass_start,
--               * const pass_end   = p + pass_length;
-+    const byte * p              = pass_start,
-+               * const pass_end = p + pass_length;
-     size_t numRanges;
- 
-     if (e.test(pass_length < 40, E_BADPASSLENGTH)) return face.error(e); 
-     // Read in basic values
--    m_flags = be::read<byte>(p);
-+    const byte flags = be::read<byte>(p);
-+    if (e.test((flags & 0x1f) && 
-+            (pt < PASS_TYPE_POSITIONING || !m_silf->aCollision() || !face.glyphs().hasBoxes()),
-+            E_BADCOLLISIONPASS))
-+        return face.error(e);
-+    m_numCollRuns = flags & 0x7;
-+    m_kernColls   = (flags >> 3) & 0x3;
-+    m_isReverseDir = (flags >> 5) & 0x1;
-     m_iMaxLoop = be::read<byte>(p);
-+    if (m_iMaxLoop < 1) m_iMaxLoop = 1;
-     be::skip<byte>(p,2); // skip maxContext & maxBackup
-     m_numRules = be::read<uint16>(p);
-+    if (e.test(!m_numRules && m_numCollRuns == 0, E_BADEMPTYPASS)) return face.error(e);
-     be::skip<uint16>(p);   // fsmOffset - not sure why we would want this
-     const byte * const pcCode = pass_start + be::read<uint32>(p) - subtable_base,
-                * const rcCode = pass_start + be::read<uint32>(p) - subtable_base,
-                * const aCode  = pass_start + be::read<uint32>(p) - subtable_base;
-     be::skip<uint32>(p);
-     m_numStates = be::read<uint16>(p);
-     m_numTransition = be::read<uint16>(p);
-     m_numSuccess = be::read<uint16>(p);
-     m_numColumns = be::read<uint16>(p);
-     numRanges = be::read<uint16>(p);
-     be::skip<uint16>(p, 3); // skip searchRange, entrySelector & rangeShift.
-     assert(p - pass_start == 40);
-     // Perform some sanity checks.
-     if ( e.test(m_numTransition > m_numStates, E_BADNUMTRANS)
-             || e.test(m_numSuccess > m_numStates, E_BADNUMSUCCESS)
-             || e.test(m_numSuccess + m_numTransition < m_numStates, E_BADNUMSTATES)
--            || e.test(numRanges == 0, E_NORANGES))
-+            || e.test(m_numRules && numRanges == 0, E_NORANGES)
-+            || e.test(m_numColumns > 0x7FFF, E_BADNUMCOLUMNS))
-         return face.error(e);
- 
-     m_successStart = m_numStates - m_numSuccess;
--    if (e.test(p + numRanges * 6 - 4 > pass_end, E_BADPASSLENGTH)) return face.error(e);
-+    // test for beyond end - 1 to account for reading uint16
-+    if (e.test(p + numRanges * 6 - 2 > pass_end, E_BADPASSLENGTH)) return face.error(e);
-     m_numGlyphs = be::peek<uint16>(p + numRanges * 6 - 4) + 1;
-     // Calculate the start of various arrays.
-     const byte * const ranges = p;
-     be::skip<uint16>(p, numRanges*3);
-     const byte * const o_rule_map = p;
-     be::skip<uint16>(p, m_numSuccess + 1);
- 
-     // More sanity checks
-@@ -126,108 +155,141 @@ bool Pass::readPass(const byte * const p
-     m_maxPreCtxt = be::read<uint8>(p);
-     if (e.test(m_minPreCtxt > m_maxPreCtxt, E_BADCTXTLENBOUNDS)) return face.error(e);
-     const byte * const start_states = p;
-     be::skip<int16>(p, m_maxPreCtxt - m_minPreCtxt + 1);
-     const uint16 * const sort_keys = reinterpret_cast<const uint16 *>(p);
-     be::skip<uint16>(p, m_numRules);
-     const byte * const precontext = p;
-     be::skip<byte>(p, m_numRules);
--    be::skip<byte>(p);     // skip reserved byte
- 
--    if (e.test(p + sizeof(uint16) > pass_end, E_BADCTXTLENS)) return face.error(e);
-+    if (e.test(p + sizeof(uint16) + sizeof(uint8) > pass_end, E_BADCTXTLENS)) return face.error(e);
-+    m_colThreshold = be::read<uint8>(p);
-+    if (m_colThreshold == 0) m_colThreshold = 10;       // A default
-     const size_t pass_constraint_len = be::read<uint16>(p);
-+
-     const uint16 * const o_constraint = reinterpret_cast<const uint16 *>(p);
-     be::skip<uint16>(p, m_numRules + 1);
-     const uint16 * const o_actions = reinterpret_cast<const uint16 *>(p);
-     be::skip<uint16>(p, m_numRules + 1);
-     const byte * const states = p;
-+    if (e.test(p + 2u*m_numTransition*m_numColumns >= pass_end, E_BADPASSLENGTH)) return face.error(e);
-     be::skip<int16>(p, m_numTransition*m_numColumns);
--    be::skip<byte>(p);          // skip reserved byte
--    if (e.test(p != pcCode, E_BADPASSCCODEPTR) || e.test(p >= pass_end, E_BADPASSLENGTH)) return face.error(e);
-+    be::skip<uint8>(p);
-+    if (e.test(p != pcCode, E_BADPASSCCODEPTR)) return face.error(e);
-     be::skip<byte>(p, pass_constraint_len);
--    if (e.test(p != rcCode, E_BADRULECCODEPTR) || e.test(p >= pass_end, E_BADPASSLENGTH)
-+    if (e.test(p != rcCode, E_BADRULECCODEPTR)
-         || e.test(size_t(rcCode - pcCode) != pass_constraint_len, E_BADCCODELEN)) return face.error(e);
-     be::skip<byte>(p, be::peek<uint16>(o_constraint + m_numRules));
--    if (e.test(p != aCode, E_BADACTIONCODEPTR) || e.test(p >= pass_end, E_BADPASSLENGTH)) return face.error(e);
-+    if (e.test(p != aCode, E_BADACTIONCODEPTR)) return face.error(e);
-     be::skip<byte>(p, be::peek<uint16>(o_actions + m_numRules));
- 
-     // We should be at the end or within the pass
-     if (e.test(p > pass_end, E_BADPASSLENGTH)) return face.error(e);
- 
-     // Load the pass constraint if there is one.
-     if (pass_constraint_len)
-     {
-         face.error_context(face.error_context() + 1);
-         m_cPConstraint = vm::Machine::Code(true, pcCode, pcCode + pass_constraint_len, 
--                                  precontext[0], be::peek<uint16>(sort_keys), *m_silf, face);
-+                                  precontext[0], be::peek<uint16>(sort_keys), *m_silf, face, PASS_TYPE_UNKNOWN);
-         if (e.test(!m_cPConstraint, E_OUTOFMEM)
--                || e.test(m_cPConstraint.status(), m_cPConstraint.status() + E_CODEFAILURE))
-+                || e.test(!m_cPConstraint, m_cPConstraint.status() + E_CODEFAILURE))
-             return face.error(e);
-         face.error_context(face.error_context() - 1);
-     }
--    if (!readRanges(ranges, numRanges, e)) return face.error(e);
--    if (!readRules(rule_map, numEntries,  precontext, sort_keys,
--                   o_constraint, rcCode, o_actions, aCode, face, e)) return false;
-+    if (m_numRules)
-+    {
-+        if (!readRanges(ranges, numRanges, e)) return face.error(e);
-+        if (!readRules(rule_map, numEntries,  precontext, sort_keys,
-+                   o_constraint, rcCode, o_actions, aCode, face, pt, e)) return false;
-+    }
- #ifdef GRAPHITE2_TELEMETRY
-     telemetry::category _states_cat(face.tele.states);
- #endif
--    return readStates(start_states, states, o_rule_map, face, e);
-+    return m_numRules ? readStates(start_states, states, o_rule_map, face, e) : true;
- }
- 
- 
- bool Pass::readRules(const byte * rule_map, const size_t num_entries,
-                      const byte *precontext, const uint16 * sort_key,
-                      const uint16 * o_constraint, const byte *rc_data,
-                      const uint16 * o_action,     const byte * ac_data,
--                     Face & face, Error &e)
-+                     Face & face, passtype pt, Error &e)
- {
-     const byte * const ac_data_end = ac_data + be::peek<uint16>(o_action + m_numRules);
-     const byte * const rc_data_end = rc_data + be::peek<uint16>(o_constraint + m_numRules);
- 
--    if (e.test(!(m_rules = new Rule [m_numRules]), E_OUTOFMEM)) return face.error(e);
-     precontext += m_numRules;
-     sort_key   += m_numRules;
-     o_constraint += m_numRules;
-     o_action += m_numRules;
- 
-     // Load rules.
-     const byte * ac_begin = 0, * rc_begin = 0,
-                * ac_end = ac_data + be::peek<uint16>(o_action),
-                * rc_end = rc_data + be::peek<uint16>(o_constraint);
-+
-+    // Allocate pools
-+    m_rules = new Rule [m_numRules];
-+    m_codes = new Code [m_numRules*2];
-+    const size_t prog_pool_sz = vm::Machine::Code::estimateCodeDataOut(ac_end - ac_data + rc_end - rc_data);
-+    m_progs = gralloc<byte>(prog_pool_sz);
-+    byte * prog_pool_free = m_progs,
-+         * prog_pool_end  = m_progs + prog_pool_sz;
-+    if (e.test(!(m_rules && m_codes && m_progs), E_OUTOFMEM)) return face.error(e);
-+
-     Rule * r = m_rules + m_numRules - 1;
-     for (size_t n = m_numRules; n; --n, --r, ac_end = ac_begin, rc_end = rc_begin)
-     {
-         face.error_context((face.error_context() & 0xFFFF00) + EC_ARULE + ((n - 1) << 24));
-         r->preContext = *--precontext;
-         r->sort       = be::peek<uint16>(--sort_key);
- #ifndef NDEBUG
-         r->rule_idx   = n - 1;
- #endif
-         if (r->sort > 63 || r->preContext >= r->sort || r->preContext > m_maxPreCtxt || r->preContext < m_minPreCtxt)
-             return false;
-         ac_begin      = ac_data + be::peek<uint16>(--o_action);
-         --o_constraint;
-         rc_begin      = be::peek<uint16>(o_constraint) ? rc_data + be::peek<uint16>(o_constraint) : rc_end;
- 
-         if (ac_begin > ac_end || ac_begin > ac_data_end || ac_end > ac_data_end
--                || rc_begin > rc_end || rc_begin > rc_data_end || rc_end > rc_data_end)
-+                || rc_begin > rc_end || rc_begin > rc_data_end || rc_end > rc_data_end
-+                || vm::Machine::Code::estimateCodeDataOut(ac_end - ac_begin + rc_end - rc_begin) > size_t(prog_pool_end - prog_pool_free))
-             return false;
--        r->action     = new vm::Machine::Code(false, ac_begin, ac_end, r->preContext, r->sort, *m_silf, face);
--        r->constraint = new vm::Machine::Code(true,  rc_begin, rc_end, r->preContext, r->sort, *m_silf, face);
-+        r->action     = new (m_codes+n*2-2) vm::Machine::Code(false, ac_begin, ac_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free);
-+        r->constraint = new (m_codes+n*2-1) vm::Machine::Code(true,  rc_begin, rc_end, r->preContext, r->sort, *m_silf, face, pt, &prog_pool_free);
- 
-         if (e.test(!r->action || !r->constraint, E_OUTOFMEM)
-                 || e.test(r->action->status() != Code::loaded, r->action->status() + E_CODEFAILURE)
-                 || e.test(r->constraint->status() != Code::loaded, r->constraint->status() + E_CODEFAILURE)
-                 || e.test(!r->constraint->immutable(), E_MUTABLECCODE))
-             return face.error(e);
-     }
- 
-+    byte * moved_progs = static_cast<byte *>(realloc(m_progs, prog_pool_free - m_progs));
-+    if (e.test(!moved_progs, E_OUTOFMEM))
-+    {
-+        if (prog_pool_free - m_progs == 0) m_progs = 0;
-+        return face.error(e);
-+    }
-+
-+    if (moved_progs != m_progs)
-+    {
-+        for (Code * c = m_codes, * const ce = c + m_numRules*2; c != ce; ++c)
-+        {
-+            c->externalProgramMoved(moved_progs - m_progs);
-+        }
-+        m_progs = moved_progs;
-+    }
-+
-     // Load the rule entries map
-     face.error_context((face.error_context() & 0xFFFF00) + EC_APASS);
-+    //TODO: Coverty: 1315804: FORWARD_NULL
-     RuleEntry * re = m_ruleMap = gralloc<RuleEntry>(num_entries);
-     if (e.test(!re, E_OUTOFMEM)) return face.error(e);
-     for (size_t n = num_entries; n; --n, ++re)
-     {
-         const ptrdiff_t rn = be::read<uint16>(rule_map);
-         if (e.test(rn >= m_numRules, E_BADRULENUM))  return face.error(e);
-         re->rule = m_rules + rn;
-     }
-@@ -320,43 +382,69 @@ bool Pass::readRanges(const byte * range
- 
-         if (e.test(ci != ci_end, E_BADRANGE))
-             return false;
-     }
-     return true;
- }
- 
- 
--void Pass::runGraphite(Machine & m, FiniteStateMachine & fsm) const
-+bool Pass::runGraphite(vm::Machine & m, FiniteStateMachine & fsm, bool reverse) const
- {
-     Slot *s = m.slotMap().segment.first();
--    if (!s || !testPassConstraint(m)) return;
--    Slot *currHigh = s->next();
-+    if (!s || !testPassConstraint(m)) return true;
-+    if (reverse)
-+    {
-+        m.slotMap().segment.reverseSlots();
-+        s = m.slotMap().segment.first();
-+    }
-+    if (m_numRules)
-+    {
-+        Slot *currHigh = s->next();
- 
- #if !defined GRAPHITE2_NTRACING
--    if (fsm.dbgout)  *fsm.dbgout << "rules" << json::array;
--    json::closer rules_array_closer(fsm.dbgout);
-+        if (fsm.dbgout)  *fsm.dbgout << "rules" << json::array;
-+        json::closer rules_array_closer(fsm.dbgout);
- #endif
- 
--    m.slotMap().highwater(currHigh);
--    int lc = m_iMaxLoop;
--    do
-+        m.slotMap().highwater(currHigh);
-+        int lc = m_iMaxLoop;
-+        do
-+        {
-+            findNDoRule(s, m, fsm);
-+            if (s && (s == m.slotMap().highwater() || m.slotMap().highpassed() || --lc == 0)) {
-+                if (!lc)
-+                    s = m.slotMap().highwater();
-+                lc = m_iMaxLoop;
-+                if (s)
-+                    m.slotMap().highwater(s->next());
-+            }
-+        } while (s);
-+    }
-+    //TODO: Use enums for flags
-+    const bool collisions = m_numCollRuns || m_kernColls;
-+
-+    if (!collisions || !m.slotMap().segment.hasCollisionInfo())
-+        return true;
-+
-+    if (m_numCollRuns)
-     {
--        findNDoRule(s, m, fsm);
--        if (s && (m.slotMap().highpassed() || s == m.slotMap().highwater() || --lc == 0)) {
--            if (!lc)
--            {
--//              if (dbgout) *dbgout << json::item << json::flat << rule_event(-1, s, 1);
--                s = m.slotMap().highwater();
--            }
--            lc = m_iMaxLoop;
--            if (s)
--                m.slotMap().highwater(s->next());
-+        if (!(m.slotMap().segment.flags() & Segment::SEG_INITCOLLISIONS))
-+        {
-+            m.slotMap().segment.positionSlots(0, 0, 0, m.slotMap().dir(), true);
-+//            m.slotMap().segment.flags(m.slotMap().segment.flags() | Segment::SEG_INITCOLLISIONS);
-         }
--    } while (s);
-+        if (!collisionShift(&m.slotMap().segment, m.slotMap().dir(), fsm.dbgout))
-+            return false;
-+    }
-+    if ((m_kernColls) && !collisionKern(&m.slotMap().segment, m.slotMap().dir(), fsm.dbgout))
-+        return false;
-+    if (collisions && !collisionFinish(&m.slotMap().segment, fsm.dbgout))
-+        return false;
-+    return true;
- }
- 
- bool Pass::runFSM(FiniteStateMachine& fsm, Slot * slot) const
- {
-     fsm.reset(slot, m_maxPreCtxt);
-     if (fsm.slots.context() < m_minPreCtxt)
-         return false;
- 
-@@ -419,18 +507,18 @@ void Pass::findNDoRule(Slot * & slot, Ma
-         {
-             if (fsm.rules.size() != 0)
-             {
-                 *fsm.dbgout << json::item << json::object;
-                 dumpRuleEventConsidered(fsm, *r);
-                 if (r != re)
-                 {
-                     const int adv = doAction(r->rule->action, slot, m);
--                    dumpRuleEventOutput(fsm, *r->rule, slot);
--                    if (r->rule->action->deletes()) fsm.slots.collectGarbage();
-+                    dumpRuleEventOutput(fsm, m, *r->rule, slot);
-+                    if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot);
-                     adjustSlot(adv, slot, fsm.slots);
-                     *fsm.dbgout << "cursor" << objectid(dslot(&fsm.slots.segment, slot))
-                             << json::close; // Close RuelEvent object
- 
-                     return;
-                 }
-                 else
-                 {
-@@ -442,47 +530,49 @@ void Pass::findNDoRule(Slot * & slot, Ma
-             }
-         }
-         else
- #endif
-         {
-             if (r != re)
-             {
-                 const int adv = doAction(r->rule->action, slot, m);
--                if (r->rule->action->deletes()) fsm.slots.collectGarbage();
-+                if (r->rule->action->deletes()) fsm.slots.collectGarbage(slot);
-                 adjustSlot(adv, slot, fsm.slots);
-                 return;
-             }
-         }
-     }
- 
-     slot = slot->next();
-+    return;
- }
- 
- #if !defined GRAPHITE2_NTRACING
- 
- void Pass::dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEntry & re) const
- {
-     *fsm.dbgout << "considered" << json::array;
-     for (const RuleEntry *r = fsm.rules.begin(); r != &re; ++r)
-     {
--        if (r->rule->preContext > fsm.slots.context())  continue;
--    *fsm.dbgout << json::flat << json::object
--                    << "id"     << r->rule - m_rules
-+        if (r->rule->preContext > fsm.slots.context())
-+            continue;
-+        *fsm.dbgout << json::flat << json::object
-+                    << "id" << r->rule - m_rules
-                     << "failed" << true
-                     << "input" << json::flat << json::object
-                         << "start" << objectid(dslot(&fsm.slots.segment, input_slot(fsm.slots, -r->rule->preContext)))
-                         << "length" << r->rule->sort
-                         << json::close  // close "input"
-                     << json::close; // close Rule object
-     }
- }
- 
- 
--void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * const last_slot) const
-+void Pass::dumpRuleEventOutput(const FiniteStateMachine & fsm, Machine & m, const Rule & r, Slot * const last_slot) const
- {
-     *fsm.dbgout     << json::item << json::flat << json::object
-                         << "id"     << &r - m_rules
-                         << "failed" << false
-                         << "input" << json::flat << json::object
-                             << "start" << objectid(dslot(&fsm.slots.segment, input_slot(fsm.slots, 0)))
-                             << "length" << r.sort - r.preContext
-                             << json::close // close "input"
-@@ -490,17 +580,17 @@ void Pass::dumpRuleEventOutput(const Fin
-                 << json::close // close considered array
-                 << "output" << json::object
-                     << "range" << json::flat << json::object
-                         << "start"  << objectid(dslot(&fsm.slots.segment, input_slot(fsm.slots, 0)))
-                         << "end"    << objectid(dslot(&fsm.slots.segment, last_slot))
-                     << json::close // close "input"
-                     << "slots"  << json::array;
-     const Position rsb_prepos = last_slot ? last_slot->origin() : fsm.slots.segment.advance();
--    fsm.slots.segment.positionSlots(0);
-+    fsm.slots.segment.positionSlots(0, 0, 0, m.slotMap().dir());
- 
-     for(Slot * slot = output_slot(fsm.slots, 0); slot != last_slot; slot = slot->next())
-         *fsm.dbgout     << dslot(&fsm.slots.segment, slot);
-     *fsm.dbgout         << json::close  // close "slots"
-                     << "postshift"  << (last_slot ? last_slot->origin() : fsm.slots.segment.advance()) - rsb_prepos
-                 << json::close;         // close "output" object
- 
- }
-@@ -546,22 +636,26 @@ bool Pass::testConstraint(const Rule & r
-         if (!ret || m.status() != Machine::finished)
-             return false;
-     }
- 
-     return true;
- }
- 
- 
--void SlotMap::collectGarbage()
-+void SlotMap::collectGarbage(Slot * &aSlot)
- {
-     for(Slot **s = begin(), *const *const se = end() - 1; s != se; ++s) {
-         Slot *& slot = *s;
-         if(slot->isDeleted() || slot->isCopied())
-+        {
-+            if (slot == aSlot)
-+                aSlot = slot->prev() ? slot->prev() : slot->next();
-             segment.freeSlot(slot);
-+        }
-     }
- }
- 
- 
- 
- int Pass::doAction(const Code *codeptr, Slot * & slot_out, vm::Machine & m) const
- {
-     assert(codeptr);
-@@ -581,40 +675,412 @@ int Pass::doAction(const Code *codeptr, 
- 
-     slot_out = *map;
-     return ret;
- }
- 
- 
- void Pass::adjustSlot(int delta, Slot * & slot_out, SlotMap & smap) const
- {
--    if (delta < 0)
-+    if (!slot_out)
-     {
--        if (!slot_out)
-+        if (smap.highpassed() || slot_out == smap.highwater())
-         {
-             slot_out = smap.segment.last();
-             ++delta;
--            if (smap.highpassed() && !smap.highwater())
-+            if (!smap.highwater())
-                 smap.highpassed(false);
-         }
-+        else
-+        {
-+            slot_out = smap.segment.first();
-+            --delta;
-+        }
-+    }
-+    if (delta < 0)
-+    {
-         while (++delta <= 0 && slot_out)
-         {
-             if (smap.highpassed() && smap.highwater() == slot_out)
-                 smap.highpassed(false);
-             slot_out = slot_out->prev();
-         }
-     }
-     else if (delta > 0)
-     {
--        if (!slot_out)
--        {
--            slot_out = smap.segment.first();
--            --delta;
--        }
-         while (--delta >= 0 && slot_out)
-         {
-             slot_out = slot_out->next();
-             if (slot_out == smap.highwater() && slot_out)
-                 smap.highpassed(true);
-         }
-     }
- }
- 
-+bool Pass::collisionShift(Segment *seg, int dir, json * const dbgout) const
-+{
-+    ShiftCollider shiftcoll(dbgout);
-+    // bool isfirst = true;
-+    bool hasCollisions = false;
-+    Slot *start = seg->first();      // turn on collision fixing for the first slot
-+    Slot *end = NULL;
-+    bool moved = false;
-+
-+#if !defined GRAPHITE2_NTRACING
-+    if (dbgout)
-+        *dbgout << "collisions" << json::array
-+            << json::flat << json::object << "num-loops" << m_numCollRuns << json::close;
-+#endif
-+
-+    while (start)
-+    {
-+#if !defined GRAPHITE2_NTRACING
-+        if (dbgout)  *dbgout << json::object << "phase" << "1" << "moves" << json::array;
-+#endif
-+        hasCollisions = false;
-+        end = NULL;
-+        // phase 1 : position shiftable glyphs, ignoring kernable glyphs
-+        for (Slot *s = start; s; s = s->next())
-+        {
-+            const SlotCollision * c = seg->collisionInfo(s);
-+            if (start && (c->flags() & (SlotCollision::COLL_FIX | SlotCollision::COLL_KERN)) == SlotCollision::COLL_FIX
-+                      && !resolveCollisions(seg, s, start, shiftcoll, false, dir, moved, hasCollisions, dbgout))
-+                return false;
-+            if (s != start && (c->flags() & SlotCollision::COLL_END))
-+            {
-+                end = s->next();
-+                break;
-+            }
-+        }
-+
-+#if !defined GRAPHITE2_NTRACING
-+        if (dbgout)
-+            *dbgout << json::close << json::close; // phase-1
-+#endif
-+
-+        // phase 2 : loop until happy. 
-+        for (int i = 0; i < m_numCollRuns - 1; ++i)
-+        {
-+            if (hasCollisions || moved)
-+            {
-+
-+#if !defined GRAPHITE2_NTRACING
-+                if (dbgout)
-+                    *dbgout << json::object << "phase" << "2a" << "loop" << i << "moves" << json::array;
-+#endif
-+                // phase 2a : if any shiftable glyphs are in collision, iterate backwards,
-+                // fixing them and ignoring other non-collided glyphs. Note that this handles ONLY
-+                // glyphs that are actually in collision from phases 1 or 2b, and working backwards
-+                // has the intended effect of breaking logjams.
-+                if (hasCollisions)
-+                {
-+                    hasCollisions = false;
-+                    #if 0
-+                    moved = true;
-+                    for (Slot *s = start; s != end; s = s->next())
-+                    {
-+                        SlotCollision * c = seg->collisionInfo(s);
-+                        c->setShift(Position(0, 0));
-+                    }
-+                    #endif
-+                    Slot *lend = end ? end->prev() : seg->last();
-+                    Slot *lstart = start->prev();
-+                    for (Slot *s = lend; s != lstart; s = s->prev())
-+                    {
-+                        SlotCollision * c = seg->collisionInfo(s);
-+                        if (start && (c->flags() & (SlotCollision::COLL_FIX | SlotCollision::COLL_KERN | SlotCollision::COLL_ISCOL))
-+                                        == (SlotCollision::COLL_FIX | SlotCollision::COLL_ISCOL)) // ONLY if this glyph is still colliding
-+                        {
-+                            if (!resolveCollisions(seg, s, lend, shiftcoll, true, dir, moved, hasCollisions, dbgout))
-+                                return false;
-+                            c->setFlags(c->flags() | SlotCollision::COLL_TEMPLOCK);
-+                        }
-+                    }
-+                }
-+
-+#if !defined GRAPHITE2_NTRACING
-+                if (dbgout)
-+                    *dbgout << json::close << json::close // phase 2a
-+                        << json::object << "phase" << "2b" << "loop" << i << "moves" << json::array;
-+#endif
-+
-+                // phase 2b : redo basic diacritic positioning pass for ALL glyphs. Each successive loop adjusts 
-+                // glyphs from their current adjusted position, which has the effect of gradually minimizing the  
-+                // resulting adjustment; ie, the final result will be gradually closer to the original location.  
-+                // Also it allows more flexibility in the final adjustment, since it is moving along the  
-+                // possible 8 vectors from successively different starting locations.
-+                if (moved)
-+                {
-+                    moved = false;
-+                    for (Slot *s = start; s != end; s = s->next())
-+                    {
-+                        SlotCollision * c = seg->collisionInfo(s);
-+                        if (start && (c->flags() & (SlotCollision::COLL_FIX | SlotCollision::COLL_TEMPLOCK
-+                                                        | SlotCollision::COLL_KERN)) == SlotCollision::COLL_FIX
-+                                  && !resolveCollisions(seg, s, start, shiftcoll, false, dir, moved, hasCollisions, dbgout))
-+                            return false;
-+                        else if (c->flags() & SlotCollision::COLL_TEMPLOCK)
-+                            c->setFlags(c->flags() & ~SlotCollision::COLL_TEMPLOCK);
-+                    }
-+                }
-+        //      if (!hasCollisions) // no, don't leave yet because phase 2b will continue to improve things
-+        //          break;
-+#if !defined GRAPHITE2_NTRACING
-+                if (dbgout)
-+                    *dbgout << json::close << json::close; // phase 2
-+#endif
-+            }
-+        }
-+        if (!end)
-+            break;
-+        start = NULL;
-+        for (Slot *s = end->prev(); s; s = s->next())
-+        {
-+            if (seg->collisionInfo(s)->flags() & SlotCollision::COLL_START)
-+            {
-+                start = s;
-+                break;
-+            }
-+        }
-+    }
-+    return true;
-+}
-+
-+bool Pass::collisionKern(Segment *seg, int dir, json * const dbgout) const
-+{
-+    KernCollider kerncoll(dbgout);
-+    Slot *start = seg->first();
-+    float ymin = 1e38f;
-+    float ymax = -1e38f;
-+    const GlyphCache &gc = seg->getFace()->glyphs();
-+
-+    // phase 3 : handle kerning of clusters
-+#if !defined GRAPHITE2_NTRACING
-+    if (dbgout)
-+        *dbgout << json::object << "phase" << "3" << "moves" << json::array;
-+#endif
-+
-+    for (Slot *s = seg->first(); s; s = s->next())
-+    {
-+        if (!gc.check(s->gid()))
-+            return false;
-+        const SlotCollision * c = seg->collisionInfo(s);
-+        const Rect &bbox = seg->theGlyphBBoxTemporary(s->gid());
-+        float y = s->origin().y + c->shift().y;
-+        ymax = max(y + bbox.tr.y, ymax);
-+        ymin = min(y + bbox.bl.y, ymin);
-+        if (start && (c->flags() & (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX))
-+                        == (SlotCollision::COLL_KERN | SlotCollision::COLL_FIX))
-+            resolveKern(seg, s, start, kerncoll, dir, ymin, ymax, dbgout);
-+        if (c->flags() & SlotCollision::COLL_END)
-+            start = NULL;
-+        if (c->flags() & SlotCollision::COLL_START)
-+            start = s;
-+    }
-+
-+#if !defined GRAPHITE2_NTRACING
-+    if (dbgout)
-+        *dbgout << json::close << json::close; // phase 3
-+#endif
-+    return true;
-+}
-+
-+bool Pass::collisionFinish(Segment *seg, GR_MAYBE_UNUSED json * const dbgout) const
-+{
-+    for (Slot *s = seg->first(); s; s = s->next())
-+    {
-+        SlotCollision *c = seg->collisionInfo(s);
-+        if (c->shift().x != 0 || c->shift().y != 0)
-+        {
-+            const Position newOffset = c->shift();
-+            const Position nullPosition(0, 0);
-+            c->setOffset(newOffset + c->offset());
-+            c->setShift(nullPosition);
-+        }
-+    }
-+//    seg->positionSlots();
-+
-+#if !defined GRAPHITE2_NTRACING
-+        if (dbgout)
-+            *dbgout << json::close;
-+#endif
-+    return true;
-+}
-+
-+// Can slot s be kerned, or is it attached to something that can be kerned?
-+static bool inKernCluster(Segment *seg, Slot *s)
-+{
-+    SlotCollision *c = seg->collisionInfo(s);
-+    if (c->flags() & SlotCollision::COLL_KERN /** && c->flags() & SlotCollision::COLL_FIX **/ )
-+        return true;
-+    while (s->attachedTo())
-+    {
-+        s = s->attachedTo();
-+        c = seg->collisionInfo(s);
-+        if (c->flags() & SlotCollision::COLL_KERN /** && c->flags() & SlotCollision::COLL_FIX **/ )
-+            return true;
-+    }
-+    return false;
-+}
-+
-+// Fix collisions for the given slot.
-+// Return true if everything was fixed, false if there are still collisions remaining.
-+// isRev means be we are processing backwards.
-+bool Pass::resolveCollisions(Segment *seg, Slot *slotFix, Slot *start,
-+        ShiftCollider &coll, GR_MAYBE_UNUSED bool isRev, int dir, bool &moved, bool &hasCol,
-+        json * const dbgout) const
-+{
-+    Slot * nbor;  // neighboring slot
-+    SlotCollision *cFix = seg->collisionInfo(slotFix);
-+    if (!coll.initSlot(seg, slotFix, cFix->limit(), cFix->margin(), cFix->marginWt(),
-+            cFix->shift(), cFix->offset(), dir, dbgout))
-+        return false;
-+    bool collides = false;
-+    // When we're processing forward, ignore kernable glyphs that preceed the target glyph.
-+    // When processing backward, don't ignore these until we pass slotFix.
-+    bool ignoreForKern = !isRev;
-+    bool rtl = dir & 1;
-+    Slot *base = slotFix;
-+    while (base->attachedTo())
-+        base = base->attachedTo();
-+    Position zero(0., 0.);
-+    
-+    // Look for collisions with the neighboring glyphs.
-+    for (nbor = start; nbor; nbor = isRev ? nbor->prev() : nbor->next())
-+    {
-+        SlotCollision *cNbor = seg->collisionInfo(nbor);
-+        bool sameCluster = nbor->isChildOf(base);
-+        if (nbor != slotFix         // don't process if this is the slot of interest
-+                      && !(cNbor->flags() & SlotCollision::COLL_IGNORE)    // don't process if ignoring
-+                      && (nbor == base || sameCluster       // process if in the same cluster as slotFix
-+                            || !inKernCluster(seg, nbor)    // or this cluster is not to be kerned
-+                            || (rtl ^ ignoreForKern))       // or it comes before(ltr) or after(rtl)
-+                      && (!isRev    // if processing forwards then good to merge otherwise only:
-+                            || !(cNbor->flags() & SlotCollision::COLL_FIX)     // merge in immovable stuff
-+                            || ((cNbor->flags() & SlotCollision::COLL_KERN) && !sameCluster)     // ignore other kernable clusters
-+                            || (cNbor->flags() & SlotCollision::COLL_ISCOL))   // test against other collided glyphs
-+                      && !coll.mergeSlot(seg, nbor, cNbor->shift(), !ignoreForKern, sameCluster, collides, false, dbgout))
-+            return false;
-+        else if (nbor == slotFix)
-+            // Switching sides of this glyph - if we were ignoring kernable stuff before, don't anymore.
-+            ignoreForKern = !ignoreForKern;
-+            
-+        if (nbor != start && (cNbor->flags() & (isRev ? SlotCollision::COLL_START : SlotCollision::COLL_END)))
-+            break;
-+    }
-+    bool isCol = false;
-+    if (collides || cFix->shift().x != 0.f || cFix->shift().y != 0.f)
-+    {
-+        Position shift = coll.resolve(seg, isCol, dbgout);
-+        // isCol has been set to true if a collision remains.
-+        if (std::fabs(shift.x) < 1e38f && std::fabs(shift.y) < 1e38f)
-+        {
-+            if (sqr(shift.x-cFix->shift().x) + sqr(shift.y-cFix->shift().y) >= m_colThreshold * m_colThreshold)
-+                moved = true;
-+            cFix->setShift(shift);
-+            if (slotFix->firstChild())
-+            {
-+                Rect bbox;
-+                Position here = slotFix->origin() + shift;
-+                float clusterMin = here.x;
-+                slotFix->firstChild()->finalise(seg, NULL, here, bbox, 0, clusterMin, rtl, false);
-+            }
-+        }
-+    }
-+    else
-+    {
-+        // This glyph is not colliding with anything.
-+#if !defined GRAPHITE2_NTRACING
-+        if (dbgout)
-+        {
-+            *dbgout << json::object 
-+                            << "missed" << objectid(dslot(seg, slotFix));
-+            coll.outputJsonDbg(dbgout, seg, -1);
-+            *dbgout << json::close;
-+        }
-+#endif
-+    }
-+
-+    // Set the is-collision flag bit.
-+    if (isCol)
-+    { cFix->setFlags(cFix->flags() | SlotCollision::COLL_ISCOL | SlotCollision::COLL_KNOWN); }
-+    else
-+    { cFix->setFlags((cFix->flags() & ~SlotCollision::COLL_ISCOL) | SlotCollision::COLL_KNOWN); }
-+    hasCol |= isCol;
-+    return true;
-+}
-+
-+float Pass::resolveKern(Segment *seg, Slot *slotFix, GR_MAYBE_UNUSED Slot *start, KernCollider &coll, int dir,
-+    float &ymin, float &ymax, json *const dbgout) const
-+{
-+    Slot *nbor; // neighboring slot
-+    float currSpace = 0.;
-+    bool collides = false;
-+    unsigned int space_count = 0;
-+    Slot *base = slotFix;
-+    while (base->attachedTo())
-+        base = base->attachedTo();
-+    SlotCollision *cFix = seg->collisionInfo(base);
-+    const GlyphCache &gc = seg->getFace()->glyphs();
-+
-+    if (base != slotFix)
-+    {
-+        cFix->setFlags(cFix->flags() | SlotCollision::COLL_KERN | SlotCollision::COLL_FIX);
-+        return 0;
-+    }
-+    bool seenEnd = (cFix->flags() & SlotCollision::COLL_END) != 0;
-+    bool isInit = false;
-+
-+    for (nbor = slotFix->next(); nbor; nbor = nbor->next())
-+    {
-+        if (nbor->isChildOf(base))
-+            continue;
-+        if (!gc.check(nbor->gid()))
-+            return 0.;
-+        const Rect &bb = seg->theGlyphBBoxTemporary(nbor->gid());
-+        SlotCollision *cNbor = seg->collisionInfo(nbor);
-+        if (bb.bl.y == 0.f && bb.tr.y == 0.f)
-+        {
-+            if (m_kernColls == InWord)
-+                break;
-+            // Add space for a space glyph.
-+            currSpace += nbor->advance();
-+            ++space_count;
-+        }
-+        else
-+        {
-+            space_count = 0; 
-+            float y = nbor->origin().y + cNbor->shift().y;
-+            ymax = max(y + bb.tr.y, ymax);
-+            ymin = min(y + bb.bl.y, ymin);
-+            if (nbor != slotFix && !(cNbor->flags() & SlotCollision::COLL_IGNORE))
-+            {
-+                seenEnd = true;
-+                if (!isInit)
-+                {
-+                    if (!coll.initSlot(seg, slotFix, cFix->limit(), cFix->margin(),
-+                                    cFix->shift(), cFix->offset(), dir, ymin, ymax, dbgout))
-+                        return 0.;
-+                    isInit = true;
-+                }
-+                collides |= coll.mergeSlot(seg, nbor, cNbor->shift(), currSpace, dir, dbgout);
-+            }
-+        }
-+        if (cNbor->flags() & SlotCollision::COLL_END)
-+        {
-+            if (seenEnd && space_count < 2)
-+                break;
-+            else
-+                seenEnd = true;
-+        }
-+    }
-+    if (collides)
-+    {
-+        Position mv = coll.resolve(seg, slotFix, dir, cFix->margin(), dbgout);
-+        coll.shift(mv, dir);
-+        Position delta = slotFix->advancePos() + mv - cFix->shift();
-+        slotFix->advance(delta);
-+        cFix->setShift(mv);
-+        return mv.x;
-+    }
-+    return 0.;
-+}
-+
-diff --git a/gfx/graphite2/src/Position.cpp b/gfx/graphite2/src/Position.cpp
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/Position.cpp
-@@ -0,0 +1,98 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2010, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+#include "inc/Position.h"
-+#include <cmath>
-+
-+using namespace graphite2;
-+
-+bool Rect::hitTest(Rect &other)
-+{
-+    if (bl.x > other.tr.x) return false;
-+    if (tr.x < other.bl.x) return false;
-+    if (bl.y > other.tr.y) return false;
-+    if (tr.y < other.bl.y) return false;
-+    return true;
-+}
-+
-+Position Rect::overlap(Position &offset, Rect &other, Position &othero)
-+{
-+    float ax = (bl.x + offset.x) - (other.tr.x + othero.x);
-+    float ay = (bl.y + offset.y) - (other.tr.y + othero.y);
-+    float bx = (other.bl.x + othero.x) - (tr.x + offset.x);
-+    float by = (other.bl.y + othero.y) - (tr.y + offset.y);
-+    return Position((ax > bx ? ax : bx), (ay > by ? ay : by));
-+}
-+
-+float boundmin(float move, float lim1, float lim2, float &error)
-+{
-+    // error is always positive for easy comparison
-+    if (move < lim1 && move < lim2)
-+    { error = 0.; return move; }
-+    else if (lim1 < lim2)
-+    { error = std::fabs(move - lim1); return lim1; }
-+    else
-+    { error = std::fabs(move - lim2); return lim2; }
-+}
-+
-+#if 0
-+Position Rect::constrainedAvoid(Position &offset, Rect &box, Rect &sdbox, Position &other, Rect &obox, Rect &osdbox)
-+{
-+    // a = max, i = min, s = sum, d = diff
-+    float eax, eay, eix, eiy, eas, eis, ead, eid;
-+    float beste = INF;
-+    Position res;
-+    // calculate the movements in each direction and the error (amount of remaining overlap)
-+    // first param is movement, second and third are movement over the constraining box
-+    float ax = boundmin(obox.tr.x + other.x - box.bl.x - offset.x + 1, tr.x - offset.x, INF, &eax);
-+    float ay = boundmin(obox.tr.y + other.y - box.bl.y - offset.y + 1, tr.y - offset.y, INF, &eay);
-+    float ix = boundmin(obox.bl.x + other.x - box.tr.x - offset.x + 1, bl.x - offset.x, INF, &eix);
-+    float iy = boundmin(obox.bl.y + other.y - box.tr.y - offset.y + 1, bl.y - offset.y, INF, &eiy);
-+    float as = boundmin(ISQRT2 * (osdbox.tr.x + other.x + other.y - sdbox.bl.x - offset.x - offset.y) + 1, tr.x - offset.x, tr.y - offset.y, &eas);
-+    float is = boundmin(ISQRT2 * (osdbox.bl.x + other.x + other.y - sdbox.tr.x - offset.x - offset.y) + 1, bl.x - offset.x, bl.y - offset.y, &eis);
-+    float ad = boundmin(ISQRT2 * (osdbox.tr.y + other.x - other.y - sdbox.bl.y - offset.x + offset.y) + 1, tr.y - offset.y, tr.x - offset.x, &ead);
-+    float id = boundmin(ISQRT2 * (osdbox.bl.y + other.x - other.y - sdbox.tr.y - offset.x + offset.y) + 1, bl.y - offset.y, bl.x - offset.x, &eid);
-+
-+    if (eax < beste)
-+    { res = Position(ax, 0); beste = eax; }
-+    if (eay < beste)
-+    { res = Position(0, ay); beste = eay; }
-+    if (eix < beste)
-+    { res = Position(ix, 0); beste = eix; }
-+    if (eiy < beste)
-+    { res = Position(0, iy); beste = eiy; }
-+    if (SQRT2 * (eas) < beste)
-+    { res = Position(as, ad); beste = SQRT2 * (eas); }
-+    if (SQRT2 * (eis) < beste)
-+    { res = Position(is, is); beste = SQRT2 * (eis); }
-+    if (SQRT2 * (ead) < beste)
-+    { res = Position(ad, ad); beste = SQRT2 * (ead); }
-+    if (SQRT2 * (eid) < beste)
-+    { res = Position(id, id); beste = SQRT2 * (eid); }
-+    return res;
-+}
-+#endif
-+
-diff --git a/gfx/graphite2/src/SegCache.cpp b/gfx/graphite2/src/SegCache.cpp
---- a/gfx/graphite2/src/SegCache.cpp
-+++ b/gfx/graphite2/src/SegCache.cpp
-@@ -35,17 +35,17 @@ of the License or (at your option) any l
- 
- 
- using namespace graphite2;
- 
- #ifndef GRAPHITE2_NSEGCACHE
- 
- SegCache::SegCache(const SegCacheStore * store, const Features & feats)
- : m_prefixLength(ePrefixLength),
--  m_maxCachedSegLength(eMaxSpliceSize),
-+//  m_maxCachedSegLength(eMaxSpliceSize),
-   m_segmentCount(0),
-   m_features(feats),
-   m_totalAccessCount(0l), m_totalMisses(0l),
-   m_purgeFactor(1.0f / (ePurgeFactor * store->maxSegmentCount()))
- {
-     m_prefixes.raw = grzeroalloc<void*>(store->maxCmapGid() + 2);
-     m_prefixes.range[SEG_CACHE_MIN_INDEX] = SEG_CACHE_UNSET_INDEX;
-     m_prefixes.range[SEG_CACHE_MAX_INDEX] = SEG_CACHE_UNSET_INDEX;
-@@ -79,17 +79,17 @@ SegCache::~SegCache()
- {
-     assert(m_prefixes.raw == NULL);
- }
- 
- SegCacheEntry* SegCache::cache(SegCacheStore * store, const uint16* cmapGlyphs, size_t length, Segment * seg, size_t charOffset)
- {
-     uint16 pos = 0;
-     if (!length) return NULL;
--    assert(length < m_maxCachedSegLength);
-+//    assert(length < m_maxCachedSegLength);
-     SegCachePrefixArray pArray = m_prefixes;
-     while (pos + 1 < m_prefixLength)
-     {
-         uint16 gid = (pos < length)? cmapGlyphs[pos] : 0;
-         if (!pArray.array[gid].raw)
-         {
-             pArray.array[gid].raw = grzeroalloc<void*>(store->maxCmapGid() + 2);
-             if (!pArray.array[gid].raw)
-diff --git a/gfx/graphite2/src/Segment.cpp b/gfx/graphite2/src/Segment.cpp
---- a/gfx/graphite2/src/Segment.cpp
-+++ b/gfx/graphite2/src/Segment.cpp
-@@ -31,48 +31,53 @@ of the License or (at your option) any l
- #include "inc/bits.h"
- #include "inc/Segment.h"
- #include "graphite2/Font.h"
- #include "inc/CharInfo.h"
- #include "inc/debug.h"
- #include "inc/Slot.h"
- #include "inc/Main.h"
- #include "inc/CmapCache.h"
--#include "inc/Bidi.h"
-+#include "inc/Collider.h"
- #include "graphite2/Segment.h"
- 
- 
- using namespace graphite2;
- 
- Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir)
- : m_freeSlots(NULL),
-   m_freeJustifies(NULL),
-   m_charinfo(new CharInfo[numchars]),
-+  m_collisions(NULL),
-   m_face(face),
-   m_silf(face->chooseSilf(script)),
-   m_first(NULL),
-   m_last(NULL),
-   m_bufSize(numchars + 10),
-   m_numGlyphs(numchars),
-   m_numCharinfo(numchars),
-   m_passBits(m_silf->aPassBits() ? -1 : 0),
-   m_defaultOriginal(0),
--  m_dir(textDir)
-+  m_dir(textDir),
-+  m_flags(((m_silf->flags() & 0x20) != 0) << 1)
- {
-     freeSlot(newSlot());
-     m_bufSize = log_binary(numchars)+1;
- }
- 
- Segment::~Segment()
- {
-     for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
-         free(*i);
--    for (AttributeRope::iterator j = m_userAttrs.begin(); j != m_userAttrs.end(); ++j)
--        free(*j);
-+    for (AttributeRope::iterator i = m_userAttrs.begin(); i != m_userAttrs.end(); ++i)
-+        free(*i);
-+    for (JustifyRope::iterator i = m_justifies.begin(); i != m_justifies.end(); ++i)
-+        free(*i);
-     delete[] m_charinfo;
-+    free(m_collisions);
- }
- 
- #ifndef GRAPHITE2_NSEGCACHE
- SegmentScopeState Segment::setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength)
- {
-     SegmentScopeState state;
-     state.numGlyphsOutsideScope = m_numGlyphs - subLength;
-     state.realFirstSlot = m_first;
-@@ -159,28 +164,35 @@ void Segment::appendSlot(int id, int cid
-         m_passBits &= theGlyph->attrs()[m_silf->aPassBits()] 
-                     | (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0);
- }
- 
- Slot *Segment::newSlot()
- {
-     if (!m_freeSlots)
-     {
-+        // check that the segment doesn't grow indefinintely
-+        if (m_numGlyphs > m_numCharinfo * MAX_SEG_GROWTH_FACTOR)
-+            return NULL;
-         int numUser = m_silf->numUser();
- #if !defined GRAPHITE2_NTRACING
-         if (m_face->logger()) ++numUser;
- #endif
-         Slot *newSlots = grzeroalloc<Slot>(m_bufSize);
--        int16 *newAttrs = grzeroalloc<int16>(numUser * m_bufSize);
--        if (!newSlots || !newAttrs) return NULL;
-+        int16 *newAttrs = grzeroalloc<int16>(m_bufSize * numUser);
-+        if (!newSlots || !newAttrs)
-+        {
-+            free(newSlots);
-+            free(newAttrs);
-+            return NULL;
-+        }
-         for (size_t i = 0; i < m_bufSize; i++)
-         {
-+            ::new (newSlots + i) Slot(newAttrs + i * numUser);
-             newSlots[i].next(newSlots + i + 1);
--            newSlots[i].userAttrs(newAttrs + i * numUser);
--            newSlots[i].setBidiClass(-1);
-         }
-         newSlots[m_bufSize - 1].next(NULL);
-         newSlots[0].next(NULL);
-         m_slots.push_back(newSlots);
-         m_userAttrs.push_back(newAttrs);
-         m_freeSlots = (m_bufSize > 1)? newSlots + 1 : NULL;
-         return newSlots;
-     }
-@@ -197,17 +209,17 @@ void Segment::freeSlot(Slot *aSlot)
-     if (aSlot->attachedTo())
-         aSlot->attachedTo()->removeChild(aSlot);
-     while (aSlot->firstChild())
-     {
-         aSlot->firstChild()->attachTo(NULL);
-         aSlot->removeChild(aSlot->firstChild());
-     }
-     // reset the slot incase it is reused
--    ::new (aSlot) Slot;
-+    ::new (aSlot) Slot(aSlot->userAttrs());
-     memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
-     // Update generation counter for debug
- #if !defined GRAPHITE2_NTRACING
-     if (m_face->logger())
-         ++aSlot->userAttrs()[m_silf->numUser()];
- #endif
-     // update next pointer
-     if (!m_freeSlots)
-@@ -301,16 +313,71 @@ void Segment::splice(size_t offset, size
-         slot->set(*srcSlot, offset, m_silf->numUser(), m_silf->numJustLevels(), numChars);
-         if (srcSlot->attachedTo())  slot->attachTo(indexmap[srcSlot->attachedTo()->index()]);
-         if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()];
-         if (srcSlot->firstChild())  slot->m_child = indexmap[srcSlot->firstChild()->index()];
-     }
- }
- #endif // GRAPHITE2_NSEGCACHE
- 
-+// reverse the slots but keep diacritics in their same position after their bases
-+void Segment::reverseSlots()
-+{
-+    m_dir = m_dir ^ 64;                 // invert the reverse flag
-+    if (m_first == m_last) return;      // skip 0 or 1 glyph runs
-+
-+    Slot *t = 0;
-+    Slot *curr = m_first;
-+    Slot *tlast;
-+    Slot *tfirst;
-+    Slot *out = 0;
-+
-+    while (curr && getSlotBidiClass(curr) == 16)
-+        curr = curr->next();
-+    if (!curr) return;
-+    tfirst = curr->prev();
-+    tlast = curr;
-+
-+    while (curr)
-+    {
-+        if (getSlotBidiClass(curr) == 16)
-+        {
-+            Slot *d = curr->next();
-+            while (d && getSlotBidiClass(d) == 16)
-+                d = d->next();
-+
-+            d = d ? d->prev() : m_last;
-+            Slot *p = out->next();    // one after the diacritics. out can't be null
-+            if (p)
-+                p->prev(d);
-+            else
-+                tlast = d;
-+            t = d->next();
-+            d->next(p);
-+            curr->prev(out);
-+            out->next(curr);
-+        }
-+        else    // will always fire first time round the loop
-+        {
-+            if (out)
-+                out->prev(curr);
-+            t = curr->next();
-+            curr->next(out);
-+            out = curr;
-+        }
-+        curr = t;
-+    }
-+    out->prev(tfirst);
-+    if (tfirst)
-+        tfirst->next(out);
-+    else
-+        m_first = out;
-+    m_last = tlast;
-+}
-+
- void Segment::linkClusters(Slot *s, Slot * end)
- {
-     end = end->next();
- 
-     for (; s != end && !s->isBase(); s = s->next());
-     Slot * ls = s;
- 
-     if (m_dir & 1)
-@@ -330,39 +397,47 @@ void Segment::linkClusters(Slot *s, Slot
-             if (!s->isBase())   continue;
- 
-             ls->sibling(s);
-             ls = s;
-         }
-     }
- }
- 
--Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd)
-+Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bool isRtl, bool isFinal)
- {
-     Position currpos(0., 0.);
-     float clusterMin = 0.;
-     Rect bbox;
- 
-+    if (currdir() != isRtl)
-+    {
-+        Slot *temp;
-+        reverseSlots();
-+        temp = iStart;
-+        iStart = iEnd;
-+        iEnd = temp;
-+    }
-     if (!iStart)    iStart = m_first;
-     if (!iEnd)      iEnd   = m_last;
- 
--    if (m_dir & 1)
-+    if (isRtl)
-     {
-         for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
-         {
-             if (s->isBase())
--                currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x);
-+                currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
-         }
-     }
-     else
-     {
-         for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
-         {
-             if (s->isBase())
--                currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x);
-+                currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
-         }
-     }
-     return currpos;
- }
- 
- 
- void Segment::associateChars(int offset, int numChars)
- {
-@@ -429,66 +504,28 @@ bool Segment::read_text(const Face *face
-     {
-     case gr_utf8:   process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break;
-     case gr_utf16:  process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break;
-     case gr_utf32:  process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break;
-     }
-     return true;
- }
- 
--void Segment::prepare_pos(const Font * /*font*/)
-+void Segment::doMirror(uint16 aMirror)
- {
--    // copy key changeable metrics into slot (if any);
--}
--
--Slot *process_bidi(Slot *start, int level, int prelevel, int &nextLevel, int dirover, int isol, int &cisol, int &isolerr, int &embederr, int init, Segment *seg, uint8 aMirror, BracketPairStack &stack);
--void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror);
--void resolveWhitespace(int baseLevel, Slot *s);
--Slot *resolveOrder(Slot * & s, const bool reordered, const int level = 0);
--
--void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
--{
--    if (slotCount() == 0)
--        return;
--
--    Slot *s;
--    int baseLevel = paradir ? 1 : 0;
--    unsigned int bmask = 0;
--    unsigned int ssize = 0;
--    for (s = first(); s; s = s->next())
-+    Slot * s;
-+    for (s = m_first; s; s = s->next())
-     {
--        if (s->getBidiClass() == -1)
--        {
--            unsigned int bAttr = glyphAttr(s->gid(), aBidi);
--            s->setBidiClass((bAttr <= 22) * bAttr);
--        }
--        bmask |= (1 << s->getBidiClass());
--        s->setBidiLevel(baseLevel);
--        if (glyphAttr(s->gid(), aMirror) && s->getBidiClass() == 21)
--            ++ssize;
--    }
--
--    BracketPairStack bstack(ssize);
--    if (bmask & (paradir ? 0x2E7892 : 0x2E789C))
--    {
--        // O(8N) algorithm, with no working data beyond what is needed for processParens
--        int nextLevel = paradir;
--        int e, i, c;
--        process_bidi(first(), baseLevel, paradir, nextLevel, 0, 0, c = 0, i = 0, e = 0, 1, this, aMirror, bstack);
--        resolveImplicit(first(), this, aMirror);
--        resolveWhitespace(baseLevel, last());
--        s = resolveOrder(s = first(), baseLevel != 0);
--        if (s)
--        {
--            first(s); last(s->prev());
--            s->prev()->next(0); s->prev(0);
--        }
--    }
--    else if (!(dir() & 4) && baseLevel && aMirror)
--    {
--        for (s = first(); s; s = s->next())
--        {
--            unsigned short g = glyphAttr(s->gid(), aMirror);
--            if (g) s->setGlyph(this, g);
--        }
-+        unsigned short g = glyphAttr(s->gid(), aMirror);
-+        if (g && (!(dir() & 4) || !glyphAttr(s->gid(), aMirror + 1)))
-+            s->setGlyph(this, g);
-     }
- }
- 
-+bool Segment::initCollisions()
-+{
-+    m_collisions = grzeroalloc<SlotCollision>(slotCount());
-+    if (!m_collisions) return false;
-+
-+    for (Slot *p = m_first; p; p = p->next())
-+        ::new (collisionInfo(p)) SlotCollision(this, p);
-+    return true;
-+}
-diff --git a/gfx/graphite2/src/Silf.cpp b/gfx/graphite2/src/Silf.cpp
---- a/gfx/graphite2/src/Silf.cpp
-+++ b/gfx/graphite2/src/Silf.cpp
-@@ -46,23 +46,25 @@ Silf::Silf() throw()
-   m_justs(0),
-   m_numPasses(0),
-   m_numJusts(0),
-   m_sPass(0),
-   m_pPass(0),
-   m_jPass(0),
-   m_bPass(0),
-   m_flags(0),
-+  m_dir(0),
-   m_aPseudo(0),
-   m_aBreak(0),
-   m_aUser(0),
-   m_aBidi(0),
-   m_aMirror(0),
-   m_aPassBits(0),
-   m_iMaxComp(0),
-+  m_aCollision(0),
-   m_aLig(0),
-   m_numPseudo(0),
-   m_nClass(0),
-   m_nLinear(0),
-   m_gEndLine(0)
- {
-     memset(&m_silfinfo, 0, sizeof m_silfinfo);
- }
-@@ -88,16 +90,20 @@ void Silf::releaseBuffers() throw()
- 
- 
- bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, Face& face, uint32 version)
- {
-     const byte * p = silf_start,
-                * const silf_end = p + lSilf;
-     Error e;
- 
-+    if (e.test(version >= 0x00060000, E_BADSILFVERSION))
-+    {
-+        releaseBuffers(); return face.error(e);
-+    }
-     if (version >= 0x00030000)
-     {
-         if (e.test(lSilf < 28, E_BADSIZE)) { releaseBuffers(); return face.error(e); }
-         be::skip<int32>(p);    // ruleVersion
-         be::skip<uint16>(p,2); // passOffset & pseudosOffset
-     }
-     else if (e.test(lSilf < 20, E_BADSIZE)) { releaseBuffers(); return face.error(e); }
-     const uint16 maxGlyph = be::read<uint16>(p);
-@@ -132,73 +138,88 @@ bool Silf::readGraphite(const byte * con
-         for (uint8 i = 0; i < m_numJusts; i++)
-         {
-             ::new(m_justs + i) Justinfo(p[0], p[1], p[2], p[3]);
-             be::skip<byte>(p,8);
-         }
-     }
- 
-     if (e.test(p + sizeof(uint16) + sizeof(uint8)*8 >= silf_end, E_BADENDJUSTS)) { releaseBuffers(); return face.error(e); }
--    m_aLig      = be::read<uint16>(p);
--    m_aUser     = be::read<uint8>(p);
--    m_iMaxComp  = be::read<uint8>(p);
--    be::skip<byte>(p,5);                        // direction and 4 reserved bytes
-+    m_aLig       = be::read<uint16>(p);
-+    m_aUser      = be::read<uint8>(p);
-+    m_iMaxComp   = be::read<uint8>(p);
-+    m_dir        = be::read<uint8>(p) - 1;
-+    m_aCollision = be::read<uint8>(p);
-+    be::skip<byte>(p,3);
-     be::skip<uint16>(p, be::read<uint8>(p));    // don't need critical features yet
-     be::skip<byte>(p);                          // reserved
-     if (e.test(p >= silf_end, E_BADCRITFEATURES))   { releaseBuffers(); return face.error(e); }
-     be::skip<uint32>(p, be::read<uint8>(p));    // don't use scriptTag array.
-     if (e.test(p + sizeof(uint16) + sizeof(uint32) >= silf_end, E_BADSCRIPTTAGS)) { releaseBuffers(); return face.error(e); }
-     m_gEndLine  = be::read<uint16>(p);          // lbGID
-     const byte * o_passes = p,
-                * const passes_start = silf_start + be::read<uint32>(p);
- 
-     const size_t num_attrs = face.glyphs().numAttrs();
-     if (e.test(m_aPseudo   >= num_attrs, E_BADAPSEUDO)
-         || e.test(m_aBreak >= num_attrs, E_BADABREAK)
-         || e.test(m_aBidi  >= num_attrs, E_BADABIDI)
-         || e.test(m_aMirror>= num_attrs, E_BADAMIRROR)
-+        || e.test(m_aCollision && m_aCollision >= num_attrs - 5, E_BADACOLLISION)
-         || e.test(m_numPasses > 128, E_BADNUMPASSES) || e.test(passes_start >= silf_end, E_BADPASSESSTART)
-         || e.test(m_pPass < m_sPass, E_BADPASSBOUND) || e.test(m_pPass > m_numPasses, E_BADPPASS) || e.test(m_sPass > m_numPasses, E_BADSPASS)
-         || e.test(m_jPass < m_pPass, E_BADJPASSBOUND) || e.test(m_jPass > m_numPasses, E_BADJPASS)
-         || e.test((m_bPass != 0xFF && (m_bPass < m_jPass || m_bPass > m_numPasses)), E_BADBPASS)
-         || e.test(m_aLig > 127, E_BADALIG))
-     {
-         releaseBuffers();
-         return face.error(e);
-     }
-     be::skip<uint32>(p, m_numPasses);
-     if (e.test(p + sizeof(uint16) >= passes_start, E_BADPASSESSTART)) { releaseBuffers(); return face.error(e); }
-     m_numPseudo = be::read<uint16>(p);
-     be::skip<uint16>(p, 3); // searchPseudo, pseudoSelector, pseudoShift
--    if (e.test(p + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start, E_BADNUMPSEUDO))
-+    m_pseudos = new Pseudo[m_numPseudo];
-+    if (e.test(p + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start, E_BADNUMPSEUDO)
-+        || e.test(!m_pseudos, E_OUTOFMEM))
-     {
-         releaseBuffers(); return face.error(e);
-     }
--    m_pseudos = new Pseudo[m_numPseudo];
-     for (int i = 0; i < m_numPseudo; i++)
-     {
-         m_pseudos[i].uid = be::read<uint32>(p);
-         m_pseudos[i].gid = be::read<uint16>(p);
-     }
- 
-     const size_t clen = readClassMap(p, passes_start - p, version, e);
--    if (e || e.test(p + clen > passes_start, E_BADPASSESSTART)) { releaseBuffers(); return face.error(e); }
-+    m_passes = new Pass[m_numPasses];
-+    if (e || e.test(p + clen > passes_start, E_BADPASSESSTART)
-+          || e.test(!m_passes, E_OUTOFMEM))
-+    { releaseBuffers(); return face.error(e); }
- 
--    m_passes = new Pass[m_numPasses];
-     for (size_t i = 0; i < m_numPasses; ++i)
-     {
-         const byte * const pass_start = silf_start + be::read<uint32>(o_passes),
-                    * const pass_end = silf_start + be::peek<uint32>(o_passes);
-         face.error_context((face.error_context() & 0xFF00) + EC_ASILF + (i << 16));
--        if (e.test(pass_start > pass_end, E_BADPASSSTART) || e.test(pass_end > silf_end, E_BADPASSEND)) {
-+        if (e.test(pass_start > pass_end, E_BADPASSSTART) 
-+                || e.test(pass_start < passes_start, E_BADPASSSTART)
-+                || e.test(pass_end > silf_end, E_BADPASSEND)) {
-             releaseBuffers(); return face.error(e);
-         }
- 
-+        enum passtype pt = PASS_TYPE_UNKNOWN;
-+        if (i >= m_jPass) pt = PASS_TYPE_JUSTIFICATION;
-+        else if (i >= m_pPass) pt = PASS_TYPE_POSITIONING;
-+        else if (i >= m_sPass) pt = PASS_TYPE_SUBSTITUTE;
-+        else pt = PASS_TYPE_LINEBREAK;
-+
-         m_passes[i].init(this);
--        if (!m_passes[i].readPass(pass_start, pass_end - pass_start, pass_start - silf_start, face, e))
-+        if (!m_passes[i].readPass(pass_start, pass_end - pass_start, pass_start - silf_start, face, pt,
-+            version, e))
-         {
-             releaseBuffers();
-             return false;
-         }
-     }
- 
-     // fill in gr_faceinfo
-     m_silfinfo.upem = face.glyphs().unitsPerEm();
-@@ -246,35 +267,38 @@ size_t Silf::readClassMap(const byte *p,
-     uint32 max_off;
-     if (version >= 0x00040000)
-         max_off = readClassOffsets<uint32>(p, data_len, e);
-     else
-         max_off = readClassOffsets<uint16>(p, data_len, e);
- 
-     if (max_off == ERROROFFSET) return ERROROFFSET;
- 
-+    if (e.test((int)max_off < m_nLinear + (m_nClass - m_nLinear) * 6, E_CLASSESTOOBIG))
-+        return ERROROFFSET;
-+
-     // Check the linear offsets are sane, these must be monotonically increasing.
-     for (const uint32 *o = m_classOffsets, * const o_end = o + m_nLinear; o != o_end; ++o)
-         if (e.test(o[0] > o[1], E_BADCLASSOFFSET))
-             return ERROROFFSET;
- 
-     // Fortunately the class data is all uint16s so we can decode these now
-     m_classData = gralloc<uint16>(max_off);
-     if (e.test(!m_classData, E_OUTOFMEM)) return ERROROFFSET;
-     for (uint16 *d = m_classData, * const d_end = d + max_off; d != d_end; ++d)
-         *d = be::read<uint16>(p);
- 
-     // Check the lookup class invariants for each non-linear class
-     for (const uint32 *o = m_classOffsets + m_nLinear, * const o_end = m_classOffsets + m_nClass; o != o_end; ++o)
-     {
-         const uint16 * lookup = m_classData + *o;
--        if (e.test(*o > max_off - 4, E_HIGHCLASSOFFSET)                        // LookupClass doesn't stretch over max_off
-+        if (e.test(*o + 4 > max_off, E_HIGHCLASSOFFSET)                        // LookupClass doesn't stretch over max_off
-          || e.test(lookup[0] == 0                                                   // A LookupClass with no looks is a suspicious thing ...
--                    || lookup[0] > (max_off - *o - 4)/2                             // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off]
--                    || lookup[3] != lookup[0] - lookup[1], E_BADCLASSLOOKUPINFO))   // rangeShift:   numIDs  - searchRange
-+                    || lookup[0] * 2 + *o + 4 > max_off                             // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off]
-+                    || lookup[3] + lookup[1] != lookup[0], E_BADCLASSLOOKUPINFO))   // rangeShift:   numIDs  - searchRange
-             return ERROROFFSET;
-     }
- 
-     return max_off;
- }
- 
- uint16 Silf::findPseudo(uint32 uid) const
- {
-@@ -285,17 +309,17 @@ uint16 Silf::findPseudo(uint32 uid) cons
- 
- uint16 Silf::findClassIndex(uint16 cid, uint16 gid) const
- {
-     if (cid > m_nClass) return -1;
- 
-     const uint16 * cls = m_classData + m_classOffsets[cid];
-     if (cid < m_nLinear)        // output class being used for input, shouldn't happen
-     {
--        for (unsigned int i = 0, n = m_classOffsets[cid + 1]; i < n; ++i, ++cls)
-+        for (unsigned int i = 0, n = m_classOffsets[cid + 1] - m_classOffsets[cid]; i < n; ++i, ++cls)
-             if (*cls == gid) return i;
-         return -1;
-     }
-     else
-     {
-         const uint16 *  min = cls + 4,      // lookups array
-                      *  max = min + cls[0]*2; // lookups aray is numIDs (cls[0]) uint16 pairs long
-         do
-@@ -326,90 +350,82 @@ uint16 Silf::getClassGlyph(uint16 cid, u
-     }
-     return 0;
- }
- 
- 
- bool Silf::runGraphite(Segment *seg, uint8 firstPass, uint8 lastPass, int dobidi) const
- {
-     assert(seg != 0);
--    SlotMap            map(*seg);
-+    SlotMap            map(*seg, m_dir);
-     FiniteStateMachine fsm(map, seg->getFace()->logger());
-     vm::Machine        m(map);
-     unsigned int       initSize = seg->slotCount();
-     uint8              lbidi = m_bPass;
- #if !defined GRAPHITE2_NTRACING
-     json * const dbgout = seg->getFace()->logger();
- #endif
- 
-     if (lastPass == 0)
-     {
-         if (firstPass == lastPass && lbidi == 0xFF)
-             return true;
-         lastPass = m_numPasses;
-     }
--    if (firstPass <= lbidi && lastPass >= lbidi && dobidi)
-+    if ((firstPass < lbidi || (dobidi && firstPass == lbidi)) && (lastPass >= lbidi || (dobidi && lastPass + 1 == lbidi)))
-         lastPass++;
-     else
-         lbidi = 0xFF;
- 
-     for (size_t i = firstPass; i < lastPass; ++i)
-     {
-         // bidi and mirroring
-         if (i == lbidi)
-         {
- #if !defined GRAPHITE2_NTRACING
-             if (dbgout)
-             {
-                 *dbgout << json::item << json::object
-                             << "id"     << -1
-                             << "slots"  << json::array;
--                seg->positionSlots(0);
-+                seg->positionSlots(0, 0, 0, m_dir);
-                 for(Slot * s = seg->first(); s; s = s->next())
-                     *dbgout     << dslot(seg, s);
-                 *dbgout         << json::close
-                             << "rules"  << json::array << json::close
-                             << json::close;
-             }
- #endif
--
--            if (!(seg->dir() & 2))
--                seg->bidiPass(m_aBidi, seg->dir() & 1, m_aMirror);
--            else if (m_aMirror)
--            {
--                Slot * s;
--                for (s = seg->first(); s; s = s->next())
--                {
--                    unsigned short g = seg->glyphAttr(s->gid(), m_aMirror);
--                    if (g && (!(seg->dir() & 4) || !seg->glyphAttr(s->gid(), m_aMirror + 1)))
--                        s->setGlyph(seg, g);
--                }
--            }
-+            if (seg->currdir() != (m_dir & 1))
-+                seg->reverseSlots();
-+            if (m_aMirror && (seg->dir() & 3) == 3)
-+                seg->doMirror(m_aMirror);
-         --i;
-+        lbidi = lastPass;
-         --lastPass;
--        lbidi = 0xFF;
-         continue;
-         }
- 
- #if !defined GRAPHITE2_NTRACING
-         if (dbgout)
-         {
-             *dbgout << json::item << json::object
-                         << "id"     << i+1
-                         << "slots"  << json::array;
--            seg->positionSlots(0);
-+            seg->positionSlots(0, 0, 0, m_dir);
-             for(Slot * s = seg->first(); s; s = s->next())
-                 *dbgout     << dslot(seg, s);
-             *dbgout         << json::close;
-         }
- #endif
- 
-         // test whether to reorder, prepare for positioning
--        if (i >= 32 || (seg->passBits() & (1 << i)) == 0)
--            m_passes[i].runGraphite(m, fsm);
-+        bool reverse = (lbidi == 0xFF) && (seg->currdir() != ((m_dir & 1) ^ m_passes[i].reverseDir()));
-+        if ((i >= 32 || (seg->passBits() & (1 << i)) == 0 || m_passes[i].collisionLoops())
-+                && !m_passes[i].runGraphite(m, fsm, reverse))
-+            return false;
-         // only subsitution passes can change segment length, cached subsegments are short for their text
-         if (m.status() != vm::Machine::finished
--            || (i < m_pPass && (seg->slotCount() > initSize * MAX_SEG_GROWTH_FACTOR
--            || (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize))))
-+            || (seg->slotCount() && seg->slotCount() * MAX_SEG_GROWTH_FACTOR < initSize))
-             return false;
-     }
-     return true;
- }
-diff --git a/gfx/graphite2/src/Slot.cpp b/gfx/graphite2/src/Slot.cpp
---- a/gfx/graphite2/src/Slot.cpp
-+++ b/gfx/graphite2/src/Slot.cpp
-@@ -24,34 +24,34 @@ Mozilla Public License (http://mozilla.o
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
- #include "inc/Segment.h"
- #include "inc/Slot.h"
- #include "inc/Silf.h"
- #include "inc/CharInfo.h"
- #include "inc/Rule.h"
-+#include "inc/Collider.h"
- 
- 
- using namespace graphite2;
- 
--Slot::Slot() :
-+Slot::Slot(int16 *user_attrs) :
-     m_next(NULL), m_prev(NULL),
-     m_glyphid(0), m_realglyphid(0), m_original(0), m_before(0), m_after(0),
-     m_index(0), m_parent(NULL), m_child(NULL), m_sibling(NULL),
-     m_position(0, 0), m_shift(0, 0), m_advance(0, 0),
-     m_attach(0, 0), m_with(0, 0), m_just(0.),
--    m_flags(0), m_attLevel(0), m_bidiCls(-1), m_bidiLevel(0), m_justs(NULL)
--    // Do not set m_userAttr since it is set *before* new is called since this
--    // is used as a positional new to reset the GrSlot
-+    m_flags(0), m_attLevel(0), m_bidiCls(-1), m_bidiLevel(0), 
-+    m_userAttr(user_attrs), m_justs(NULL)
- {
- }
- 
- // take care, this does not copy any of the GrSlot pointer fields
--void Slot::set(const Slot & orig, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars)
-+void Slot::set(const Slot & orig, int charOffset, size_t sizeAttr, size_t justLevels, size_t numChars)
- {
-     // leave m_next and m_prev unchanged
-     m_glyphid = orig.m_glyphid;
-     m_realglyphid = orig.m_realglyphid;
-     m_original = orig.m_original + charOffset;
-     if (charOffset + int(orig.m_before) < 0)
-         m_before = 0;
-     else
-@@ -68,95 +68,104 @@ void Slot::set(const Slot & orig, int ch
-     m_advance = orig.m_advance;
-     m_attach = orig.m_attach;
-     m_with = orig.m_with;
-     m_flags = orig.m_flags;
-     m_attLevel = orig.m_attLevel;
-     m_bidiCls = orig.m_bidiCls;
-     m_bidiLevel = orig.m_bidiLevel;
-     if (m_userAttr && orig.m_userAttr)
--        memcpy(m_userAttr, orig.m_userAttr, numUserAttr * sizeof(*m_userAttr));
-+        memcpy(m_userAttr, orig.m_userAttr, sizeAttr * sizeof(*m_userAttr));
-     if (m_justs && orig.m_justs)
-         memcpy(m_justs, orig.m_justs, SlotJustify::size_of(justLevels));
- }
- 
- void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos)
- {
-     m_before += numCharInfo;
-     m_after += numCharInfo;
-     m_position = m_position + relpos;
- }
- 
--Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin)
-+Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal)
- {
-+    SlotCollision *coll = NULL;
-     if (attrLevel && m_attLevel > attrLevel) return Position(0, 0);
--    float scale = 1.0;
--    Position shift(m_shift.x * ((seg->dir() & 1) * -2 + 1) + m_just, m_shift.y);
-+    float scale = font ? font->scale() : 1.0f;
-+    Position shift(m_shift.x * (rtl * -2 + 1) + m_just, m_shift.y);
-     float tAdvance = m_advance.x + m_just;
-+    if (isFinal && (coll = seg->collisionInfo(this)))
-+    {
-+        const Position &collshift = coll->offset();
-+        if (!(coll->flags() & SlotCollision::COLL_KERN) || rtl)
-+            shift = shift + collshift;
-+    }
-     const GlyphFace * glyphFace = seg->getFace()->glyphs().glyphSafe(glyph());
-     if (font)
-     {
-         scale = font->scale();
-         shift *= scale;
-         if (font->isHinted() && glyphFace)
--            tAdvance = (m_advance.x - glyphFace->theAdvance().x + m_just) * scale + font->advance(m_glyphid);
-+            tAdvance = (m_advance.x - glyphFace->theAdvance().x + m_just) * scale + font->advance(glyph());
-         else
-             tAdvance *= scale;
-     }    
-     Position res;
- 
-     m_position = base + shift;
-     if (!m_parent)
-     {
-         res = base + Position(tAdvance, m_advance.y * scale);
--        clusterMin = base.x;
-+        clusterMin = m_position.x;
-     }
-     else
-     {
-         float tAdv;
-         m_position += (m_attach - m_with) * scale;
--        tAdv = m_advance.x >= 0.5 ? m_position.x + tAdvance - shift.x : 0.f;
-+        tAdv = m_advance.x >= 0.5f ? m_position.x + tAdvance - shift.x : 0.f;
-         res = Position(tAdv, 0);
--        if ((m_advance.x >= 0.5 || m_position.x < 0) && m_position.x < clusterMin) clusterMin = m_position.x;
-+        if ((m_advance.x >= 0.5f || m_position.x < 0) && m_position.x < clusterMin) clusterMin = m_position.x;
-     }
- 
-     if (glyphFace)
-     {
-         Rect ourBbox = glyphFace->theBBox() * scale + m_position;
-         bbox = bbox.widen(ourBbox);
-     }
- 
-     if (m_child && m_child != this && m_child->attachedTo() == this)
-     {
--        Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin);
--        if ((!m_parent || m_advance.x >= 0.5) && tRes.x > res.x) res = tRes;
-+        Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin, rtl, isFinal);
-+        if ((!m_parent || m_advance.x >= 0.5f) && tRes.x > res.x) res = tRes;
-     }
- 
-     if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent)
-     {
--        Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin);
-+        Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin, rtl, isFinal);
-         if (tRes.x > res.x) res = tRes;
-     }
-     
-     if (!m_parent && clusterMin < base.x)
-     {
--        Position adj = Position(base.x - clusterMin, 0.);
-+        Position adj = Position(m_position.x - clusterMin, 0.);
-         res += adj;
-         m_position += adj;
-         if (m_child) m_child->floodShift(adj);
-     }
-     return res;
- }
- 
--int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
-+int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel, bool rtl)
- {
-     Position base;
-+    if (glyph() >= seg->getFace()->glyphs().numGlyphs())
-+        return 0;
-     Rect bbox = seg->theGlyphBBoxTemporary(glyph());
-     float clusterMin = 0.;
--    Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin);
-+    Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin, rtl, false);
- 
-     switch (metrics(metric))
-     {
-     case kgmetLsb :
-         return static_cast<uint32>(bbox.bl.x);
-     case kgmetRsb :
-         return static_cast<uint32>(res.x - bbox.tr.x);
-     case kgmetBbTop :
-@@ -175,19 +184,20 @@ int32 Slot::clusterMetric(const Segment 
-         return static_cast<uint32>(res.x);
-     case kgmetAdvHeight :
-         return static_cast<uint32>(res.y);
-     default :
-         return 0;
-     }
- }
- 
-+#define SLOTGETCOLATTR(x) { SlotCollision *c = seg->collisionInfo(this); return c ? int(c-> x) : 0; }
-+
- int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
- {
--    if (!this) return 0;
-     if (ind == gr_slatUserDefnV1)
-     {
-         ind = gr_slatUserDefn;
-         subindex = 0;
-     }
-     else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
-     {
-         int indx = ind - gr_slatJStretch;
-@@ -205,37 +215,66 @@ int Slot::getAttr(const Segment *seg, at
-     case gr_slatAttYOff :   return 0;
-     case gr_slatAttWithX :  return int(m_with.x);
-     case gr_slatAttWithY :  return int(m_with.y);
-     case gr_slatAttWithXOff:
-     case gr_slatAttWithYOff:return 0;
-     case gr_slatAttLevel :  return m_attLevel;
-     case gr_slatBreak :     return seg->charinfo(m_original)->breakWeight();
-     case gr_slatCompRef :   return 0;
--    case gr_slatDir :       if (m_bidiCls == -1)
--                                const_cast<Slot *>(this)->setBidiClass(seg->glyphAttr(gid(), seg->silf()->aBidi()));
--                            return m_bidiCls;
-+    case gr_slatDir :       return seg->dir() & 1;
-     case gr_slatInsert :    return isInsertBefore();
-     case gr_slatPosX :      return int(m_position.x); // but need to calculate it
-     case gr_slatPosY :      return int(m_position.y);
-     case gr_slatShiftX :    return int(m_shift.x);
-     case gr_slatShiftY :    return int(m_shift.y);
-     case gr_slatMeasureSol: return -1; // err what's this?
-     case gr_slatMeasureEol: return -1;
-     case gr_slatJWidth:     return int(m_just);
-     case gr_slatUserDefn :  return m_userAttr[subindex];
-     case gr_slatSegSplit :  return seg->charinfo(m_original)->flags() & 3;
-     case gr_slatBidiLevel:  return m_bidiLevel;
--    default :               return 0;
-+    case gr_slatColFlags :		{ SlotCollision *c = seg->collisionInfo(this); return c ? c->flags() : 0; }
-+    case gr_slatColLimitblx :	SLOTGETCOLATTR(limit().bl.x)
-+    case gr_slatColLimitbly :	SLOTGETCOLATTR(limit().bl.y)
-+    case gr_slatColLimittrx :	SLOTGETCOLATTR(limit().tr.x)
-+    case gr_slatColLimittry :	SLOTGETCOLATTR(limit().tr.y)
-+    case gr_slatColShiftx :		SLOTGETCOLATTR(offset().x)
-+    case gr_slatColShifty :		SLOTGETCOLATTR(offset().y)
-+    case gr_slatColMargin :		SLOTGETCOLATTR(margin())
-+    case gr_slatColMarginWt :	SLOTGETCOLATTR(marginWt())
-+    case gr_slatColExclGlyph :	SLOTGETCOLATTR(exclGlyph())
-+    case gr_slatColExclOffx :	SLOTGETCOLATTR(exclOffset().x)
-+    case gr_slatColExclOffy :	SLOTGETCOLATTR(exclOffset().y)
-+    case gr_slatSeqClass :		SLOTGETCOLATTR(seqClass())
-+	case gr_slatSeqProxClass :	SLOTGETCOLATTR(seqProxClass())
-+    case gr_slatSeqOrder :		SLOTGETCOLATTR(seqOrder())
-+    case gr_slatSeqAboveXoff :	SLOTGETCOLATTR(seqAboveXoff())
-+    case gr_slatSeqAboveWt :	SLOTGETCOLATTR(seqAboveWt())
-+    case gr_slatSeqBelowXlim :	SLOTGETCOLATTR(seqBelowXlim())
-+    case gr_slatSeqBelowWt :	SLOTGETCOLATTR(seqBelowWt())
-+    case gr_slatSeqValignHt :	SLOTGETCOLATTR(seqValignHt())
-+    case gr_slatSeqValignWt :	SLOTGETCOLATTR(seqValignWt())
-+    default : return 0;
-     }
- }
- 
-+#define SLOTCOLSETATTR(x) { \
-+        SlotCollision *c = seg->collisionInfo(this); \
-+        if (c) { c-> x ; c->setFlags(c->flags() & ~SlotCollision::COLL_KNOWN); } \
-+        break; }
-+#define SLOTCOLSETCOMPLEXATTR(t, y, x) { \
-+        SlotCollision *c = seg->collisionInfo(this); \
-+        if (c) { \
-+        const t &s = c-> y; \
-+        c-> x ; c->setFlags(c->flags() & ~SlotCollision::COLL_KNOWN); } \
-+        break; }
-+
- void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
- {
--    if (!this) return;
-     if (ind == gr_slatUserDefnV1)
-     {
-         ind = gr_slatUserDefn;
-         subindex = 0;
-     }
-     else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
-     {
-         int indx = ind - gr_slatJStretch;
-@@ -247,22 +286,22 @@ void Slot::setAttr(Segment *seg, attrCod
-     case gr_slatAdvX :  m_advance.x = value; break;
-     case gr_slatAdvY :  m_advance.y = value; break;
-     case gr_slatAttTo :
-     {
-         const uint16 idx = uint16(value);
-         if (idx < map.size() && map[idx])
-         {
-             Slot *other = map[idx];
--            if (other == this) break;
-+            if (other == this || other == m_parent) break;
-             if (m_parent) m_parent->removeChild(this);
--            if (other->child(this))
-+            if (!other->isChildOf(this) && other->child(this))
-             {
-                 attachTo(other);
--                if (((seg->dir() & 1) != 0) ^ (idx > subindex))
-+                if ((map.dir() != 0) ^ (idx > subindex))
-                     m_with = Position(advance(), 0);
-                 else        // normal match to previous root
-                     m_attach = Position(other->advance(), 0);
-             }
-         }
-         break;
-     }
-     case gr_slatAttX :          m_attach.x = value; break;
-@@ -275,29 +314,52 @@ void Slot::setAttr(Segment *seg, attrCod
-     case gr_slatAttWithYOff :   break;
-     case gr_slatAttLevel :
-         m_attLevel = byte(value);
-         break;
-     case gr_slatBreak :
-         seg->charinfo(m_original)->breakWeight(value);
-         break;
-     case gr_slatCompRef :   break;      // not sure what to do here
--    case gr_slatDir :       m_bidiCls = value; break;
-+    case gr_slatDir : break;
-     case gr_slatInsert :
-         markInsertBefore(value? true : false);
-         break;
-     case gr_slatPosX :      break; // can't set these here
-     case gr_slatPosY :      break;
-     case gr_slatShiftX :    m_shift.x = value; break;
-     case gr_slatShiftY :    m_shift.y = value; break;
-     case gr_slatMeasureSol :    break;
-     case gr_slatMeasureEol :    break;
-     case gr_slatJWidth :    just(value); break;
-     case gr_slatSegSplit :  seg->charinfo(m_original)->addflags(value & 3); break;
-     case gr_slatUserDefn :  m_userAttr[subindex] = value; break;
-+    case gr_slatColFlags :  {
-+        SlotCollision *c = seg->collisionInfo(this);
-+        if (c)
-+            c->setFlags(value);
-+        break; }
-+    case gr_slatColLimitblx :	SLOTCOLSETCOMPLEXATTR(Rect, limit(), setLimit(Rect(Position(value, s.bl.y), s.tr)))
-+    case gr_slatColLimitbly :	SLOTCOLSETCOMPLEXATTR(Rect, limit(), setLimit(Rect(Position(s.bl.x, value), s.tr)))
-+    case gr_slatColLimittrx :	SLOTCOLSETCOMPLEXATTR(Rect, limit(), setLimit(Rect(s.bl, Position(value, s.tr.y))))
-+    case gr_slatColLimittry :	SLOTCOLSETCOMPLEXATTR(Rect, limit(), setLimit(Rect(s.bl, Position(s.tr.x, value))))
-+    case gr_slatColMargin :		SLOTCOLSETATTR(setMargin(value))
-+    case gr_slatColMarginWt :	SLOTCOLSETATTR(setMarginWt(value))
-+    case gr_slatColExclGlyph :	SLOTCOLSETATTR(setExclGlyph(value))
-+    case gr_slatColExclOffx :	SLOTCOLSETCOMPLEXATTR(Position, exclOffset(), setExclOffset(Position(value, s.y)))
-+    case gr_slatColExclOffy :	SLOTCOLSETCOMPLEXATTR(Position, exclOffset(), setExclOffset(Position(s.x, value)))
-+    case gr_slatSeqClass :		SLOTCOLSETATTR(setSeqClass(value))
-+	case gr_slatSeqProxClass :	SLOTCOLSETATTR(setSeqProxClass(value))
-+    case gr_slatSeqOrder :		SLOTCOLSETATTR(setSeqOrder(value))
-+    case gr_slatSeqAboveXoff :	SLOTCOLSETATTR(setSeqAboveXoff(value))
-+    case gr_slatSeqAboveWt :	SLOTCOLSETATTR(setSeqAboveWt(value))
-+    case gr_slatSeqBelowXlim :	SLOTCOLSETATTR(setSeqBelowXlim(value))
-+    case gr_slatSeqBelowWt :	SLOTCOLSETATTR(setSeqBelowWt(value))
-+    case gr_slatSeqValignHt :	SLOTCOLSETATTR(setSeqValignHt(value))
-+    case gr_slatSeqValignWt :	SLOTCOLSETATTR(setSeqValignWt(value))
-     default :
-         break;
-     }
- }
- 
- int Slot::getJustify(const Segment *seg, uint8 level, uint8 subindex) const
- {
-     if (level && level >= seg->silf()->numJustLevels()) return 0;
-@@ -369,46 +431,54 @@ bool Slot::removeChild(Slot *ap)
- }
- 
- bool Slot::removeSibling(Slot *ap)
- {
-     if (this == ap || !m_sibling) return false;
-     else if (ap == m_sibling)
-     {
-         m_sibling = m_sibling->nextSibling();
-+        ap->sibling(NULL);
-         return true;
-     }
-     else
-         return m_sibling->removeSibling(ap);
-     return true;
- }
- 
- void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
- {
-     m_glyphid = glyphid;
-+    m_bidiCls = -1;
-     if (!theGlyph)
-     {
-         theGlyph = seg->getFace()->glyphs().glyphSafe(glyphid);
-         if (!theGlyph)
-         {
-             m_realglyphid = 0;
-             m_advance = Position(0.,0.);
-             return;
-         }
-     }
-     m_realglyphid = theGlyph->attrs()[seg->silf()->aPseudo()];
-+    if (m_realglyphid > seg->getFace()->glyphs().numGlyphs())
-+        m_realglyphid = 0;
-     const GlyphFace *aGlyph = theGlyph;
-     if (m_realglyphid)
-     {
-         aGlyph = seg->getFace()->glyphs().glyphSafe(m_realglyphid);
-         if (!aGlyph) aGlyph = theGlyph;
-     }
-     m_advance = Position(aGlyph->theAdvance().x, 0.);
-     if (seg->silf()->aPassBits())
-+    {
-         seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]);
-+        if (seg->silf()->numPasses() > 16)
-+            seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()+1] << 16);
-+    }
- }
- 
- void Slot::floodShift(Position adj)
- {
-     m_position += adj;
-     if (m_child) m_child->floodShift(adj);
-     if (m_sibling) m_sibling->floodShift(adj);
- }
-@@ -420,8 +490,35 @@ void SlotJustify::LoadSlot(const Slot *s
-         Justinfo *justs = seg->silf()->justAttrs() + i;
-         int16 *v = values + i * NUMJUSTPARAMS;
-         v[0] = seg->glyphAttr(s->gid(), justs->attrStretch());
-         v[1] = seg->glyphAttr(s->gid(), justs->attrShrink());
-         v[2] = seg->glyphAttr(s->gid(), justs->attrStep());
-         v[3] = seg->glyphAttr(s->gid(), justs->attrWeight());
-     }
- }
-+
-+Slot * Slot::nextInCluster(const Slot *s) const
-+{
-+    Slot *base;
-+    if (s->firstChild())
-+        return s->firstChild();
-+    else if (s->nextSibling())
-+        return s->nextSibling();
-+    while ((base = s->attachedTo()))
-+    {
-+        // if (base->firstChild() == s && base->nextSibling())
-+        if (base->nextSibling())
-+            return base->nextSibling();
-+        s = base;
-+    }
-+    return NULL;
-+}
-+
-+bool Slot::isChildOf(const Slot *base) const
-+{
-+    if (m_parent == base)
-+        return true;
-+    else if (!m_parent)
-+        return false;
-+    else
-+        return m_parent->isChildOf(base);
-+}
-diff --git a/gfx/graphite2/src/Sparse.cpp b/gfx/graphite2/src/Sparse.cpp
---- a/gfx/graphite2/src/Sparse.cpp
-+++ b/gfx/graphite2/src/Sparse.cpp
-@@ -25,17 +25,17 @@ License, as published by the Free Softwa
- of the License or (at your option) any later version.
- */
- #include <cassert>
- #include "inc/Sparse.h"
- #include "inc/bits.h"
- 
- using namespace graphite2;
- 
--sparse::chunk sparse::empty_chunk = {0,0};
-+const sparse::chunk sparse::empty_chunk = {0,0};
- 
- sparse::~sparse() throw()
- {
-     if (m_array.map == &empty_chunk) return;
-     free(m_array.values);
- }
- 
- 
-diff --git a/gfx/graphite2/src/TtfUtil.cpp b/gfx/graphite2/src/TtfUtil.cpp
---- a/gfx/graphite2/src/TtfUtil.cpp
-+++ b/gfx/graphite2/src/TtfUtil.cpp
-@@ -57,18 +57,20 @@ Description
-     Forward declarations
- ***********************************************************************************************/
- 
- /***********************************************************************************************
-     Local Constants and static variables
- ***********************************************************************************************/
- namespace 
- {
-+#ifdef ALL_TTFUTILS
-     // max number of components allowed in composite glyphs
-     const int kMaxGlyphComponents = 8;
-+#endif
- 
-     template <int R, typename T>
-     inline float fixed_to_float(const T f) {
-         return float(f)/float(2^R);
-     }
- 
- /*----------------------------------------------------------------------------------------------
-     Table of standard Postscript glyph names. From Martin Hosken. Disagress with ttfdump.exe
-@@ -222,69 +224,79 @@ bool GetTableInfo(const Tag TableTag, co
- /*----------------------------------------------------------------------------------------------
-     Check the specified table. Tests depend on the table type.
-     Return true if successful, false otherwise.
- ----------------------------------------------------------------------------------------------*/
- bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
- {
-     using namespace Sfnt;
-     
--    if (pTable == 0) return false;
-+    if (pTable == 0 || lTableSize < 4) return false;
- 
-     switch(TableId)
-     {
-     case Tag::cmap: // cmap
-     {
-         const Sfnt::CharacterCodeMap * const pCmap 
-             = reinterpret_cast<const Sfnt::CharacterCodeMap *>(pTable);
-+        if (lTableSize < sizeof(Sfnt::CharacterCodeMap))
-+            return false;
-         return be::swap(pCmap->version) == 0;
-     }
- 
-     case Tag::head: // head
-     {
-         const Sfnt::FontHeader * const pHead 
-             = reinterpret_cast<const Sfnt::FontHeader *>(pTable);
-+        if (lTableSize < sizeof(Sfnt::FontHeader))
-+            return false;
-         bool r = be::swap(pHead->version) == OneFix
-             && be::swap(pHead->magic_number) == FontHeader::MagicNumber
-             && be::swap(pHead->glyph_data_format)
-                     == FontHeader::GlypDataFormat 
-             && (be::swap(pHead->index_to_loc_format)
-                     == FontHeader::ShortIndexLocFormat 
-                 || be::swap(pHead->index_to_loc_format)
-                     == FontHeader::LongIndexLocFormat) 
-             && sizeof(FontHeader) <= lTableSize;
-         return r;
-     }
- 
-     case Tag::post: // post
-     {
-         const Sfnt::PostScriptGlyphName * const pPost 
-             = reinterpret_cast<const Sfnt::PostScriptGlyphName *>(pTable);
-+        if (lTableSize < sizeof(Sfnt::PostScriptGlyphName))
-+            return false;
-         const fixed format = be::swap(pPost->format);
-         bool r = format == PostScriptGlyphName::Format1 
-             || format == PostScriptGlyphName::Format2 
-             || format == PostScriptGlyphName::Format3 
-             || format == PostScriptGlyphName::Format25;
-         return r;
-     }
- 
-     case Tag::hhea: // hhea
-     {
-         const Sfnt::HorizontalHeader * pHhea = 
-             reinterpret_cast<const Sfnt::HorizontalHeader *>(pTable);
-+        if (lTableSize < sizeof(Sfnt::HorizontalHeader))
-+            return false;
-         bool r = be::swap(pHhea->version) == OneFix
-             && be::swap(pHhea->metric_data_format) == 0
-             && sizeof (Sfnt::HorizontalHeader) <= lTableSize;
-         return r;
-     }
- 
-     case Tag::maxp: // maxp
-     {
-         const Sfnt::MaximumProfile * pMaxp = 
-             reinterpret_cast<const Sfnt::MaximumProfile *>(pTable);
-+        if (lTableSize < sizeof(Sfnt::MaximumProfile))
-+            return false;
-         bool r = be::swap(pMaxp->version) == OneFix
-             && sizeof(Sfnt::MaximumProfile) <= lTableSize;
-         return r;
-     }
- 
-     case Tag::OS_2: // OS/2
-     {
-         const Sfnt::Compatibility * pOs2 
-@@ -319,16 +331,18 @@ bool CheckTable(const Tag TableId, const
-             return false;
-         break;
-     }
- 
-     case Tag::name:
-     {
-         const Sfnt::FontNames * pName 
-             = reinterpret_cast<const Sfnt::FontNames *>(pTable);
-+        if (lTableSize < sizeof(Sfnt::FontNames))
-+            return false;
-         return be::swap(pName->format) == 0;
-     }
- 
-     default:
-         break;
-     }
- 
-     return true;
-@@ -791,27 +805,27 @@ bool HorMetrics(gid16 nGlyphId, const vo
-         reinterpret_cast<const Sfnt::HorizontalMetric *>(pHmtx);
- 
-     const Sfnt::HorizontalHeader * phhea = 
-         reinterpret_cast<const Sfnt::HorizontalHeader *>(pHhea);
- 
-     size_t cLongHorMetrics = be::swap(phhea->num_long_hor_metrics);
-     if (nGlyphId < cLongHorMetrics) 
-     {   // glyph id is acceptable
--        if (nGlyphId * sizeof(Sfnt::HorizontalMetric) >= lHmtxSize) return false;
-+        if ((nGlyphId + 1) * sizeof(Sfnt::HorizontalMetric) > lHmtxSize) return false;
-         nAdvWid = be::swap(phmtx[nGlyphId].advance_width);
-         nLsb = be::swap(phmtx[nGlyphId].left_side_bearing);
-     }
-     else
-     {
-         // guard against bad glyph id
-         size_t lLsbOffset = sizeof(Sfnt::HorizontalMetric) * cLongHorMetrics +
-             sizeof(int16) * (nGlyphId - cLongHorMetrics); // offset in bytes
-         // We test like this as LsbOffset is an offset not a length.
--        if (lLsbOffset > lHmtxSize - sizeof(int16))
-+        if (lLsbOffset >= lHmtxSize - sizeof(int16) || cLongHorMetrics == 0)
-         {
-             nLsb = 0;
-             return false;
-         }
-         nAdvWid = be::swap(phmtx[cLongHorMetrics - 1].advance_width);
-         nLsb = be::peek<int16>(reinterpret_cast<const byte *>(phmtx) + lLsbOffset);
-     }
- 
-@@ -833,31 +847,33 @@ const void * FindCmapSubtable(const void
-     {
-         if (be::swap(pTable->encoding[i].platform_id) == nPlatformId &&
-                 (nEncodingId == -1 || be::swap(pTable->encoding[i].platform_specific_id) == nEncodingId))
-         {
-             uint32 offset = be::swap(pTable->encoding[i].offset);
-             const uint8 * pRtn = reinterpret_cast<const uint8 *>(pCmap) + offset;
-             if (length)
-             {
--                if (offset > length) return NULL;
-+                if (offset > length - 2) return NULL;
-                 uint16 format = be::read<uint16>(pRtn);
-                 if (format == 4)
-                 {
-+                    if (offset > length - 4) return NULL;
-                     uint16 subTableLength = be::peek<uint16>(pRtn);
-                     if (i + 1 == csuPlatforms)
-                     {
-                         if (subTableLength > length - offset)
-                             return NULL;
-                     }
-                     else if (subTableLength > be::swap(pTable->encoding[i+1].offset))
-                         return NULL;
-                 }
-                 if (format == 12)
-                 {
-+                    if (offset > length - 6) return NULL;
-                     uint32 subTableLength = be::peek<uint32>(pRtn);
-                     if (i + 1 == csuPlatforms)
-                     {
-                         if (subTableLength > length - offset)
-                             return NULL;
-                     }
-                     else if (subTableLength > be::swap(pTable->encoding[i+1].offset))
-                         return NULL;
-@@ -868,48 +884,80 @@ const void * FindCmapSubtable(const void
-     }
- 
-     return 0;
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Check the Microsoft Unicode subtable for expected values
- ----------------------------------------------------------------------------------------------*/
--bool CheckCmapSubtable4(const void * pCmapSubtable4)
-+bool CheckCmapSubtable4(const void * pCmapSubtable4, size_t table_len /*, unsigned int maxgid*/)
- {
-     if (!pCmapSubtable4) return false;
-     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable4);
--    // Bob H says ome freeware TT fonts have version 1 (eg, CALIGULA.TTF) 
-+    // Bob H say some freeware TT fonts have version 1 (eg, CALIGULA.TTF) 
-     // so don't check subtable version. 21 Mar 2002 spec changes version to language.
-     if (be::swap(pTable->format) != 4) return false;
-     const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtable4);
-     uint16 length = be::swap(pTable4->length);
-+    if (length > table_len)
-+        return false;
-     if (length < sizeof(Sfnt::CmapSubTableFormat4))
-         return false;
-     uint16 nRanges = be::swap(pTable4->seg_count_x2) >> 1;
-     if (length < sizeof(Sfnt::CmapSubTableFormat4) + 4 * nRanges * sizeof(uint16))
-         return false;
-     // check last range is properly terminated
-     uint16 chEnd = be::peek<uint16>(pTable4->end_code + nRanges - 1);
--    return (chEnd == 0xFFFF);
-+    if (chEnd != 0xFFFF)
-+        return false;
-+#if 0
-+    int lastend = -1;
-+    for (int i = 0; i < nRanges; ++i)
-+    {
-+        uint16 end = be::peek<uint16>(pTable4->end_code + i);
-+        uint16 start = be::peek<uint16>(pTable4->end_code + nRanges + 1 + i);
-+        int16 delta = be::peek<int16>(pTable4->end_code + 2*nRanges + 1 + i);
-+        uint16 offset = be::peek<uint16>(pTable4->end_code + 3*nRanges + 1 + i);
-+        if (lastend >= end || lastend >= start)
-+            return false;
-+        if (offset)
-+        {
-+            const uint16 *gstart = pTable4->end_code + 3*nRanges + 1 + i + (offset >> 1);
-+            const uint16 *gend = gstart + end - start;
-+            if ((char *)gend >= (char *)pCmapSubtable4 + length)
-+                return false;
-+            while (gstart <= gend)
-+            {
-+                uint16 g = be::peek<uint16>(gstart++);
-+                if (g && ((g + delta) & 0xFFFF) > maxgid)
-+                    return false;
-+            }
-+        }
-+        else if (((delta + end) & 0xFFFF) > maxgid)
-+            return false;
-+        lastend = end;
-+    }
-+#endif
-+    return true;
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Return the Glyph ID for the given Unicode ID in the Microsoft Unicode subtable.
-     (Actually this code only depends on subtable being format 4.)
-     Return 0 if the Unicode ID is not in the subtable.
- ----------------------------------------------------------------------------------------------*/
- gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey)
- {
-     const Sfnt::CmapSubTableFormat4 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtabel4);
- 
-     uint16 nSeg = be::swap(pTable->seg_count_x2) >> 1;
-   
-     uint16 n;
--        const uint16 * pLeft, * pMid;
-+    const uint16 * pLeft, * pMid;
-     uint16 cMid, chStart, chEnd;
- 
-     if (rangeKey)
-     {
-         pMid = &(pTable->end_code[rangeKey]);
-         chEnd = be::peek<uint16>(pMid);
-     }
-     else
-@@ -1027,29 +1075,41 @@ unsigned int CmapSubtable4NextCodepoint(
-     if (pRangeKey)
-         *pRangeKey = iRange + 1;
-     return be::peek<uint16>(pStartCode + iRange + 1);
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Check the Microsoft UCS-4 subtable for expected values.
- ----------------------------------------------------------------------------------------------*/
--bool CheckCmapSubtable12(const void *pCmapSubtable12)
-+bool CheckCmapSubtable12(const void *pCmapSubtable12, size_t table_len /*, unsigned int maxgid*/)
- {
-     if (!pCmapSubtable12)  return false;
-     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable12);
-     if (be::swap(pTable->format) != 12)
-         return false;
-     const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmapSubtable12);
-     uint32 length = be::swap(pTable12->length);
-+    if (length > table_len)
-+        return false;
-     if (length < sizeof(Sfnt::CmapSubTableFormat12))
-         return false;
--    
--    return (length == (sizeof(Sfnt::CmapSubTableFormat12) + (be::swap(pTable12->num_groups) - 1)
--        * sizeof(uint32) * 3));
-+    uint32 num_groups = be::swap(pTable12->num_groups);
-+    if (length != (sizeof(Sfnt::CmapSubTableFormat12) + (num_groups - 1) * sizeof(uint32) * 3))
-+        return false;
-+#if 0
-+    for (unsigned int i = 0; i < num_groups; ++i)
-+    {
-+        if (be::swap(pTable12->group[i].end_char_code)  - be::swap(pTable12->group[i].start_char_code) + be::swap(pTable12->group[i].start_glyph_id) > maxgid)
-+            return false;
-+        if (i > 0 && be::swap(pTable12->group[i].start_char_code) <= be::swap(pTable12->group[i-1].end_char_code))
-+            return false;
-+    }
-+#endif
-+    return true;
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Return the Glyph ID for the given Unicode ID in the Microsoft UCS-4 subtable.
-     (Actually this code only depends on subtable being format 12.)
-     Return 0 if the Unicode ID is not in the subtable.
- ----------------------------------------------------------------------------------------------*/
- gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey)
-@@ -1140,49 +1200,53 @@ unsigned int CmapSubtable12NextCodepoint
-     Technically this method should return an unsigned long but it is unlikely the offset will
-         exceed 2^31.
- ----------------------------------------------------------------------------------------------*/
- size_t LocaLookup(gid16 nGlyphId, 
-         const void * pLoca, size_t lLocaSize, 
-         const void * pHead) // throw (std::out_of_range)
- {
-     const Sfnt::FontHeader * pTable = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
-+    size_t res = -2;
- 
-     // CheckTable verifies the index_to_loc_format is valid
-     if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::ShortIndexLocFormat)
-     { // loca entries are two bytes and have been divided by two
--        if (nGlyphId < (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
-+        if (lLocaSize > 1 && nGlyphId + 1u < lLocaSize >> 1) // allow sentinel value to be accessed
-         {
-             const uint16 * pShortTable = reinterpret_cast<const uint16 *>(pLoca);
--            return (be::peek<uint16>(pShortTable + nGlyphId) << 1);
-+            res = be::peek<uint16>(pShortTable + nGlyphId) << 1;
-+            if (res == static_cast<size_t>(be::peek<uint16>(pShortTable + nGlyphId + 1) << 1))
-+                return -1;
-         }
-     }
--    
--    if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
-+    else if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
-     { // loca entries are four bytes
--        if (nGlyphId < (lLocaSize >> 2) - 1)
-+        if (lLocaSize > 3 && nGlyphId + 1u < lLocaSize >> 2)
-         {
-             const uint32 * pLongTable = reinterpret_cast<const uint32 *>(pLoca);
--            return be::peek<uint32>(pLongTable + nGlyphId);
-+            res = be::peek<uint32>(pLongTable + nGlyphId);
-+            if (res == static_cast<size_t>(be::peek<uint32>(pLongTable + nGlyphId + 1)))
-+                return -1;
-         }
-     }
- 
-     // only get here if glyph id was bad
--    return -1;
-+    return res;
-     //throw std::out_of_range("glyph id out of range for font");
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Return a pointer into the glyf table based on the given offset (from LocaLookup).
-     Return NULL on error.
- ----------------------------------------------------------------------------------------------*/
- void * GlyfLookup(const void * pGlyf, size_t nGlyfOffset, size_t nTableLen)
- {
-     const uint8 * pByte = reinterpret_cast<const uint8 *>(pGlyf);
--        if (nGlyfOffset == size_t(-1) || nGlyfOffset >= nTableLen)
-+        if (nGlyfOffset + pByte < pByte || nGlyfOffset + sizeof(Sfnt::Glyph) >= nTableLen)
-             return NULL;
-     return const_cast<uint8 *>(pByte + nGlyfOffset);
- }
- 
- /*----------------------------------------------------------------------------------------------
-     Get the bounding box coordinates for a simple glyf entry (non-composite).
-     Return true if successful, false otherwise.
- ----------------------------------------------------------------------------------------------*/
-@@ -1784,17 +1848,16 @@ bool GlyfContourEndPoints(gid16 nGlyphId
-     cnPoints - count of points from largest end point obtained from GlyfContourEndPoints
-     prgnX & prgnY - should point to buffers large enough to hold cnPoints integers
-         The ranges are parallel so that coordinates for point(n) are found at offset n in 
-         both ranges. These points are in absolute coordinates.
-     prgfOnCurve - should point to a buffer a large enough to hold cnPoints bytes (bool)
-         This range is parallel to the prgnX & prgnY
-     Return true if successful, false otherwise. On false, all points may be INT_MIN
-         False may indicate a white space glyph, a multi-level composite, or a corrupt font
--    // TODO: doesn't support composite glyphs whose components are themselves components
-         It's not clear from the TTF spec when the transforms should be applied. Should the 
-         transform be done before or after attachment point calcs? (current code - before) 
-         Should the transform be applied to other offsets? (currently - no; however commented 
-         out code is in place so that if CompoundGlyph::UnscaledOffset on the MS rasterizer is 
-         clear (typical) then yes, and if CompoundGlyph::ScaledOffset on the Apple rasterizer is 
-         clear (typical?) then no). See GetComponentTransform.
-         It's also unclear where point numbering with attachment poinst starts 
-         (currently - first point number is relative to whole glyph, second point number is 
-diff --git a/gfx/graphite2/src/call_machine.cpp b/gfx/graphite2/src/call_machine.cpp
---- a/gfx/graphite2/src/call_machine.cpp
-+++ b/gfx/graphite2/src/call_machine.cpp
-@@ -65,57 +65,60 @@ using namespace graphite2;
- using namespace vm;
- 
- struct regbank  {
-     slotref         is;
-     slotref *       map;
-     SlotMap       & smap;
-     slotref * const map_base;
-     const instr * & ip;
-+    uint8           direction;
-     int8            flags;
- };
- 
- typedef bool        (* ip_t)(registers);
- 
- // Pull in the opcode definitions
- // We pull these into a private namespace so these otherwise common names dont
- // pollute the toplevel namespace.
- namespace {
- #define smap    reg.smap
- #define seg     smap.segment
- #define is      reg.is
- #define ip      reg.ip
- #define map     reg.map
- #define mapb    reg.map_base
- #define flags   reg.flags
-+#define dir     reg.direction
- 
- #include "inc/opcodes.h"
- 
- #undef smap
- #undef seg
- #undef is
- #undef ip
- #undef map
- #undef mapb
- #undef flags
-+#undef dir
- }
- 
- Machine::stack_t  Machine::run(const instr   * program,
-                                const byte    * data,
-                                slotref     * & map)
- 
- {
-     assert(program != 0);
- 
-     // Declare virtual machine registers
-     const instr   * ip = program-1;
-     const byte    * dp = data;
-     stack_t       * sp = _stack + Machine::STACK_GUARD,
-             * const sb = sp;
--    regbank         reg = {*map, map, _map, _map.begin()+_map.context(), ip, 0};
-+    regbank         reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0};
- 
-     // Run the program        
-     while ((reinterpret_cast<ip_t>(*++ip))(dp, sp, sb, reg)) {}
-     const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
- 
-     check_final_stack(sp);
-     map = reg.map;
-     *map = reg.is;
-diff --git a/gfx/graphite2/src/direct_machine.cpp b/gfx/graphite2/src/direct_machine.cpp
---- a/gfx/graphite2/src/direct_machine.cpp
-+++ b/gfx/graphite2/src/direct_machine.cpp
-@@ -56,16 +56,17 @@ using namespace vm;
- 
- namespace {
- 
- const void * direct_run(const bool          get_table_mode,
-                         const instr       * program,
-                         const byte        * data,
-                         Machine::stack_t  * stack,
-                         slotref         * & __map,
-+                        uint8                _dir,
-                         SlotMap           * __smap=0)
- {
-     // We need to define and return to opcode table from within this function 
-     // other inorder to take the addresses of the instruction bodies.
-     #include "inc/opcode_table.h"
-     if (get_table_mode)
-         return opcode_table;
- 
-@@ -74,16 +75,17 @@ const void * direct_run(const bool      
-     const byte        * dp = data;
-     Machine::stack_t  * sp = stack + Machine::STACK_GUARD,
-                 * const sb = sp;
-     SlotMap         & smap = *__smap;
-     Segment          & seg = smap.segment;
-     slotref             is = *__map,
-                      * map = __map,
-               * const mapb = smap.begin()+smap.context();
-+    uint8            dir = _dir;
-     int8             flags = 0;
-     
-     // start the program
-     goto **ip;
- 
-     // Pull in the opcode definitions
-     #include "inc/opcodes.h"
-     
-@@ -104,14 +106,14 @@ const opcode_t * Machine::getOpcodeTable
- 
- Machine::stack_t  Machine::run(const instr   * program,
-                                const byte    * data,
-                                slotref     * & is)
- {
-     assert(program != 0);
-     
-     const stack_t *sp = static_cast<const stack_t *>(
--                direct_run(false, program, data, _stack, is, &_map));
-+                direct_run(false, program, data, _stack, is, _map.dir(), &_map));
-     const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
-     check_final_stack(sp);
-     return ret;
- }
- 
-diff --git a/gfx/graphite2/src/files.mk b/gfx/graphite2/src/files.mk
---- a/gfx/graphite2/src/files.mk
-+++ b/gfx/graphite2/src/files.mk
-@@ -42,29 +42,32 @@
-     $($(_NS)_BASE)/src/gr_char_info.cpp \
-     $($(_NS)_BASE)/src/gr_face.cpp \
-     $($(_NS)_BASE)/src/gr_features.cpp \
-     $($(_NS)_BASE)/src/gr_font.cpp \
-     $($(_NS)_BASE)/src/gr_logging.cpp \
-     $($(_NS)_BASE)/src/gr_segment.cpp \
-     $($(_NS)_BASE)/src/gr_slot.cpp \
-     $($(_NS)_BASE)/src/json.cpp \
--    $($(_NS)_BASE)/src/Bidi.cpp \
-     $($(_NS)_BASE)/src/CachedFace.cpp \
-     $($(_NS)_BASE)/src/CmapCache.cpp \
-     $($(_NS)_BASE)/src/Code.cpp \
-+    $($(_NS)_BASE)/src/Collider.cpp \
-+    $($(_NS)_BASE)/src/Decompressor.cpp \
-     $($(_NS)_BASE)/src/Face.cpp \
-     $($(_NS)_BASE)/src/FeatureMap.cpp \
-     $($(_NS)_BASE)/src/FileFace.cpp \
-     $($(_NS)_BASE)/src/Font.cpp \
-     $($(_NS)_BASE)/src/GlyphCache.cpp \
-     $($(_NS)_BASE)/src/GlyphFace.cpp \
-+    $($(_NS)_BASE)/src/Intervals.cpp \
-     $($(_NS)_BASE)/src/Justifier.cpp \
-     $($(_NS)_BASE)/src/NameTable.cpp \
-     $($(_NS)_BASE)/src/Pass.cpp \
-+    $($(_NS)_BASE)/src/Position.cpp \
-     $($(_NS)_BASE)/src/SegCache.cpp \
-     $($(_NS)_BASE)/src/SegCacheEntry.cpp \
-     $($(_NS)_BASE)/src/SegCacheStore.cpp \
-     $($(_NS)_BASE)/src/Segment.cpp \
-     $($(_NS)_BASE)/src/Silf.cpp \
-     $($(_NS)_BASE)/src/Slot.cpp \
-     $($(_NS)_BASE)/src/Sparse.cpp \
-     $($(_NS)_BASE)/src/TtfUtil.cpp \
-@@ -73,25 +76,29 @@
- $(_NS)_PRIVATE_HEADERS = \
-     $($(_NS)_BASE)/src/inc/bits.h \
-     $($(_NS)_BASE)/src/inc/debug.h \
-     $($(_NS)_BASE)/src/inc/json.h \
-     $($(_NS)_BASE)/src/inc/CachedFace.h \
-     $($(_NS)_BASE)/src/inc/CharInfo.h \
-     $($(_NS)_BASE)/src/inc/CmapCache.h \
-     $($(_NS)_BASE)/src/inc/Code.h \
-+    $($(_NS)_BASE)/src/inc/Collider.h \
-+    $($(_NS)_BASE)/src/inc/Compression.h \
-+    $($(_NS)_BASE)/src/inc/Decompressor.h \
-     $($(_NS)_BASE)/src/inc/Endian.h \
-     $($(_NS)_BASE)/src/inc/Error.h \
-     $($(_NS)_BASE)/src/inc/Face.h \
-     $($(_NS)_BASE)/src/inc/FeatureMap.h \
-     $($(_NS)_BASE)/src/inc/FeatureVal.h \
-     $($(_NS)_BASE)/src/inc/FileFace.h \
-     $($(_NS)_BASE)/src/inc/Font.h \
-     $($(_NS)_BASE)/src/inc/GlyphCache.h \
-     $($(_NS)_BASE)/src/inc/GlyphFace.h \
-+    $($(_NS)_BASE)/src/inc/Intervals.h \
-     $($(_NS)_BASE)/src/inc/List.h \
-     $($(_NS)_BASE)/src/inc/locale2lcid.h \
-     $($(_NS)_BASE)/src/inc/Machine.h \
-     $($(_NS)_BASE)/src/inc/Main.h \
-     $($(_NS)_BASE)/src/inc/NameTable.h \
-     $($(_NS)_BASE)/src/inc/opcode_table.h \
-     $($(_NS)_BASE)/src/inc/opcodes.h \
-     $($(_NS)_BASE)/src/inc/Pass.h \
-diff --git a/gfx/graphite2/src/gr_face.cpp b/gfx/graphite2/src/gr_face.cpp
---- a/gfx/graphite2/src/gr_face.cpp
-+++ b/gfx/graphite2/src/gr_face.cpp
-@@ -41,17 +41,17 @@ extern json *global_log;
- 
- namespace
- {
-     bool load_face(Face & face, unsigned int options)
-     {
- #ifdef GRAPHITE2_TELEMETRY
-         telemetry::category _misc_cat(face.tele.misc);
- #endif
--        Face::Table silf(face, Tag::Silf);
-+        Face::Table silf(face, Tag::Silf, 0x00050000);
-         if (silf)   options &= ~gr_face_dumbRendering;
-         else if (!(options &  gr_face_dumbRendering))
-             return false;
- 
-         if (!face.readGlyphs(options))
-             return false;
- 
-         if (silf)
-diff --git a/gfx/graphite2/src/gr_logging.cpp b/gfx/graphite2/src/gr_logging.cpp
---- a/gfx/graphite2/src/gr_logging.cpp
-+++ b/gfx/graphite2/src/gr_logging.cpp
-@@ -19,24 +19,25 @@
-     Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-     internet at http://www.fsf.org/licenses/lgpl.html.
- 
- Alternatively, the contents of this file may be used under the terms of the
- Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
--#include <stdio.h>
-+#include <cstdio>
- 
- #include "graphite2/Log.h"
- #include "inc/debug.h"
- #include "inc/CharInfo.h"
- #include "inc/Slot.h"
- #include "inc/Segment.h"
- #include "inc/json.h"
-+#include "inc/Collider.h"
- 
- #if defined _WIN32
- #include "windows.h"
- #endif
- 
- using namespace graphite2;
- 
- #if !defined GRAPHITE2_NTRACING
-@@ -179,16 +180,17 @@ json & graphite2::operator << (json & j,
- 
- 
- json & graphite2::operator << (json & j, const dslot & ds) throw()
- {
-     assert(ds.first);
-     assert(ds.second);
-     const Segment & seg = *ds.first;
-     const Slot & s = *ds.second;
-+    const SlotCollision *cslot = seg.collisionInfo(ds.second);
- 
-     j << json::object
-         << "id"             << objectid(ds)
-         << "gid"            << s.gid()
-         << "charinfo" << json::flat << json::object
-             << "original"       << s.original()
-             << "before"         << s.before()
-             << "after"          << s.after()
-@@ -215,16 +217,38 @@ json & graphite2::operator << (json & j,
-         j   << json::close;
-     if (s.firstChild())
-     {
-         j   << "children" << json::flat << json::array;
-         for (const Slot *c = s.firstChild(); c; c = c->nextSibling())
-             j   << objectid(dslot(&seg, c));
-         j       << json::close;
-     }
-+    if (cslot)
-+    {
-+		// Note: the reason for using Positions to lump together related attributes is to make the 
-+		// JSON output slightly more compact.
-+        j << "collision" << json::flat << json::object
-+//              << "shift" << cslot->shift() -- not used pass level, only within the collision routine itself
-+              << "offset" << cslot->offset()
-+              << "limit" << cslot->limit()
-+              << "flags" << cslot->flags()
-+              << "margin" << Position(cslot->margin(), cslot->marginWt())
-+              << "exclude" << cslot->exclGlyph()
-+              << "excludeoffset" << cslot->exclOffset();
-+		if (cslot->seqOrder() != 0)
-+		{
-+			j << "seqclass" << Position(cslot->seqClass(), cslot->seqProxClass())
-+				<< "seqorder" << cslot->seqOrder()
-+				<< "seqabove" << Position(cslot->seqAboveXoff(), cslot->seqAboveWt())
-+				<< "seqbelow" << Position(cslot->seqBelowXlim(), cslot->seqBelowWt())
-+				<< "seqvalign" << Position(cslot->seqValignHt(), cslot->seqValignWt());
-+		}
-+        j << json::close;
-+    }
-     return j << json::close;
- }
- 
- 
- graphite2::objectid::objectid(const dslot & ds) throw()
- {
-     const Slot * const p = ds.second;
-     uint32 s = reinterpret_cast<size_t>(p);
-diff --git a/gfx/graphite2/src/gr_segment.cpp b/gfx/graphite2/src/gr_segment.cpp
---- a/gfx/graphite2/src/gr_segment.cpp
-+++ b/gfx/graphite2/src/gr_segment.cpp
-@@ -43,21 +43,17 @@ namespace
-       Segment* pRes=new Segment(nChars, face, script, dir);
- 
-       
-       if (!pRes->read_text(face, pFeats, enc, pStart, nChars) || !pRes->runGraphite())
-       {
-         delete pRes;
-         return NULL;
-       }
--      // run the line break passes
--      // run the substitution passes
--      pRes->prepare_pos(font);
--      // run the positioning passes
--      pRes->finalise(font);
-+      pRes->finalise(font, true);
- 
-       return static_cast<gr_segment*>(pRes);
-   }
- 
- 
- }
- 
- 
-diff --git a/gfx/graphite2/src/gr_slot.cpp b/gfx/graphite2/src/gr_slot.cpp
---- a/gfx/graphite2/src/gr_slot.cpp
-+++ b/gfx/graphite2/src/gr_slot.cpp
-@@ -98,21 +98,21 @@ float gr_slot_advance_X(const gr_slot* p
-         if (face && font->isHinted())
-             res = (res - face->glyphs().glyph(p->gid())->theAdvance().x) * scale + font->advance(p->gid());
-         else
-             res = res * scale;
-     }
-     return res;
- }
- 
--float gr_slot_advance_Y(const gr_slot *p/*not NULL*/, const gr_face *face, const gr_font *font)
-+float gr_slot_advance_Y(const gr_slot *p/*not NULL*/, GR_MAYBE_UNUSED const gr_face *face, const gr_font *font)
- {
-     assert(p);
-     float res = p->advancePos().y;
--    if (font && (face || !face))
-+    if (font)
-         return res * font->scale();
-     else
-         return res;
- }
-         
- int gr_slot_before(const gr_slot* p/*not NULL*/)
- {
-     assert(p);
-diff --git a/gfx/graphite2/src/inc/Code.h b/gfx/graphite2/src/inc/Code.h
---- a/gfx/graphite2/src/inc/Code.h
-+++ b/gfx/graphite2/src/inc/Code.h
-@@ -36,32 +36,41 @@ of the License or (at your option) any l
- #include "inc/Main.h"
- #include "inc/Machine.h"
- 
- namespace graphite2 {
- 
- class Silf;
- class Face;
- 
-+enum passtype {
-+    PASS_TYPE_UNKNOWN = 0,
-+    PASS_TYPE_LINEBREAK,
-+    PASS_TYPE_SUBSTITUTE,
-+    PASS_TYPE_POSITIONING,
-+    PASS_TYPE_JUSTIFICATION
-+};
-+
- namespace vm {
- 
- class Machine::Code
- {
- public:
-     enum status_t 
-     {
-         loaded,
-         alloc_failed, 
-         invalid_opcode, 
-         unimplemented_opcode_used,
-         out_of_range_data,
-         jump_past_end,
-         arguments_exhausted,
-         missing_return,
--        nested_context_item
-+        nested_context_item,
-+        underfull_stack
-     };
- 
- private:
-     class decoder;
- 
-     instr *     _code;
-     byte  *     _data;
-     size_t      _data_size,
-@@ -72,40 +81,51 @@ private:
-                 _modify,
-                 _delete;
-     mutable bool _own;
- 
-     void release_buffers() throw ();
-     void failure(const status_t) throw();
- 
- public:
-+    static size_t estimateCodeDataOut(size_t num_bytecodes);
-+
-     Code() throw();
-     Code(bool is_constraint, const byte * bytecode_begin, const byte * const bytecode_end,
--         uint8 pre_context, uint16 rule_length, const Silf &, const Face &);
-+         uint8 pre_context, uint16 rule_length, const Silf &, const Face &,
-+         enum passtype pt, byte * * const _out = 0);
-     Code(const Machine::Code &) throw();
-     ~Code() throw();
-     
-     Code & operator=(const Code &rhs) throw();
--    operator bool () const throw();
--    status_t      status() const throw();
--    bool          constraint() const throw();
--    size_t        dataSize() const throw();
--    size_t        instructionCount() const throw();
--    bool          immutable() const throw();
--    bool          deletes() const throw();
--    size_t        maxRef() const throw();
-+    operator bool () const throw()                  { return _code && status() == loaded; }
-+    status_t      status() const throw()            { return _status; }
-+    bool          constraint() const throw()        { return _constraint; }
-+    size_t        dataSize() const throw()          { return _data_size; }
-+    size_t        instructionCount() const throw()  { return _instr_count; }
-+    bool          immutable() const throw()         { return !(_delete || _modify); }
-+    bool          deletes() const throw()           { return _delete; }
-+    size_t        maxRef() const throw()            { return _max_ref; }
-+    void          externalProgramMoved(ptrdiff_t) throw();
- 
-     int32 run(Machine &m, slotref * & map) const;
-     
-     CLASS_NEW_DELETE;
- };
- 
-+inline
-+size_t  Machine::Code::estimateCodeDataOut(size_t n_bc)
-+{
-+    return n_bc * (sizeof(instr)+sizeof(byte));
-+}
-+
-+
- inline Machine::Code::Code() throw()
- : _code(0), _data(0), _data_size(0), _instr_count(0), _max_ref(0),
--  _status(loaded), _constraint(false), _modify(false),_delete(false),
-+  _status(loaded), _constraint(false), _modify(false), _delete(false),
-   _own(false)
- {
- }
- 
- inline Machine::Code::Code(const Machine::Code &obj) throw ()
-  :  _code(obj._code), 
-     _data(obj._data), 
-     _data_size(obj._data_size), 
-@@ -131,45 +151,19 @@ inline Machine::Code & Machine::Code::op
-     _constraint  = rhs._constraint;
-     _modify      = rhs._modify;
-     _delete      = rhs._delete;
-     _own         = rhs._own; 
-     rhs._own = false;
-     return *this;
- }
- 
--inline Machine::Code::operator bool () const throw () {
--    return _code && status() == loaded;
--}
--
--inline Machine::Code::status_t Machine::Code::status() const throw() {
--    return _status;
--}
--
--inline bool Machine::Code::constraint() const throw() {
--    return _constraint;
--}
--
--inline size_t Machine::Code::dataSize() const throw() {
--    return _data_size;
--}
--
--inline size_t Machine::Code::instructionCount() const throw() {
--    return _instr_count;
--}
--
--inline bool Machine::Code::immutable() const throw()
-+inline void Machine::Code::externalProgramMoved(ptrdiff_t dist) throw()
- {
--  return !(_delete || _modify);
--}
--
--inline bool Machine::Code::deletes() const throw()
--{
--  return _delete;
--}
--
--inline size_t Machine::Code::maxRef() const throw()
--{
--    return _max_ref;
-+    if (_code && !_own)
-+    {
-+        _code += dist / sizeof(instr);
-+        _data += dist;
-+    }
- }
- 
- } // namespace vm
- } // namespace graphite2
-diff --git a/gfx/graphite2/src/inc/Collider.h b/gfx/graphite2/src/inc/Collider.h
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/inc/Collider.h
-@@ -0,0 +1,242 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2010, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+#pragma once
-+
-+#include "inc/List.h"
-+#include "inc/Position.h"
-+#include "inc/Intervals.h"
-+#include "inc/debug.h"
-+
-+namespace graphite2 {
-+
-+class json;
-+class Slot;
-+class Segment;
-+
-+#define SLOTCOLSETUINTPROP(x, y) uint16 x() const { return _ ##x; } void y (uint16 v) { _ ##x = v; }
-+#define SLOTCOLSETINTPROP(x, y) int16 x() const { return _ ##x; } void y (int16 v) { _ ##x = v; }
-+#define SLOTCOLSETPOSITIONPROP(x, y) const Position &x() const { return _ ##x; } void y (const Position &v) { _ ##x = v; }
-+
-+// Slot attributes related to collision-fixing
-+class SlotCollision
-+{
-+public:
-+    enum {
-+    //  COLL_TESTONLY = 0,  // default - test other glyphs for collision with this one, but don't move this one
-+        COLL_FIX = 1,       // fix collisions involving this glyph
-+        COLL_IGNORE = 2,    // ignore this glyph altogether
-+        COLL_START = 4,     // start of range of possible collisions
-+        COLL_END = 8,       // end of range of possible collisions
-+        COLL_KERN = 16,     // collisions with this glyph are fixed by adding kerning space after it
-+        COLL_ISCOL = 32,    // this glyph has a collision
-+        COLL_KNOWN = 64,    // we've figured out what's happening with this glyph
-+        COLL_TEMPLOCK = 128,    // Lock glyphs that have been given priority positioning
-+        ////COLL_JUMPABLE = 128,    // moving glyphs may jump this stationary glyph in any direction - DELETE
-+        ////COLL_OVERLAP = 256,    // use maxoverlap to restrict - DELETE
-+    };
-+    
-+    // Behavior for the collision.order attribute. To GDL this is an enum, to us it's a bitfield, with only 1 bit set
-+    // Allows for easier inversion.
-+    enum {
-+        SEQ_ORDER_LEFTDOWN = 1,
-+        SEQ_ORDER_RIGHTUP = 2,
-+        SEQ_ORDER_NOABOVE = 4,
-+        SEQ_ORDER_NOBELOW = 8,
-+        SEQ_ORDER_NOLEFT = 16,
-+        SEQ_ORDER_NORIGHT = 32
-+    };
-+    
-+    SlotCollision(Segment *seg, Slot *slot);
-+    void initFromSlot(Segment *seg, Slot *slot);
-+    
-+    const Rect &limit() const { return _limit; }
-+    void setLimit(const Rect &r) { _limit = r; }
-+    SLOTCOLSETPOSITIONPROP(shift, setShift)
-+    SLOTCOLSETPOSITIONPROP(offset, setOffset)
-+    SLOTCOLSETPOSITIONPROP(exclOffset, setExclOffset)
-+    SLOTCOLSETUINTPROP(margin, setMargin)
-+    SLOTCOLSETUINTPROP(marginWt, setMarginWt)
-+    SLOTCOLSETUINTPROP(flags, setFlags)
-+    SLOTCOLSETUINTPROP(exclGlyph, setExclGlyph)
-+    SLOTCOLSETUINTPROP(seqClass, setSeqClass)
-+    SLOTCOLSETUINTPROP(seqProxClass, setSeqProxClass)
-+    SLOTCOLSETUINTPROP(seqOrder, setSeqOrder)
-+    SLOTCOLSETINTPROP(seqAboveXoff, setSeqAboveXoff)
-+    SLOTCOLSETUINTPROP(seqAboveWt, setSeqAboveWt)
-+    SLOTCOLSETINTPROP(seqBelowXlim, setSeqBelowXlim)
-+    SLOTCOLSETUINTPROP(seqBelowWt, setSeqBelowWt)
-+    SLOTCOLSETUINTPROP(seqValignHt, setSeqValignHt)
-+    SLOTCOLSETUINTPROP(seqValignWt, setSeqValignWt)
-+
-+    float getKern(int dir) const;
-+    
-+private:
-+    Rect        _limit;
-+    Position    _shift;     // adjustment within the given pass
-+    Position    _offset;    // total adjustment for collisions
-+    Position    _exclOffset;
-+    uint16		_margin;
-+    uint16		_marginWt;
-+    uint16		_flags;
-+    uint16		_exclGlyph;
-+    uint16		_seqClass;
-+	uint16		_seqProxClass;
-+    uint16		_seqOrder;
-+    int16		_seqAboveXoff;
-+    uint16		_seqAboveWt;
-+    int16		_seqBelowXlim;
-+    uint16		_seqBelowWt;
-+    uint16		_seqValignHt;
-+    uint16		_seqValignWt;
-+	
-+};  // end of class SlotColllision
-+
-+struct BBox;
-+struct SlantBox;
-+
-+class ShiftCollider
-+{
-+public:
-+    typedef std::pair<float, float> fpair;
-+    typedef Vector<fpair> vfpairs;
-+    typedef vfpairs::iterator ivfpairs;
-+
-+    ShiftCollider(json *dbgout);
-+    ~ShiftCollider() throw() { };
-+
-+    bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint,
-+                float margin, float marginMin, const Position &currShift,
-+                const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout);
-+    bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, bool isAfter, 
-+                bool sameCluster, bool &hasCol, bool isExclusion, GR_MAYBE_UNUSED json * const dbgout);
-+    Position resolve(Segment *seg, bool &isCol, GR_MAYBE_UNUSED json * const dbgout);
-+    void addBox_slope(bool isx, const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, float weight, float m, bool minright, int mode);
-+    void removeBox(const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, int mode);
-+    const Position &origin() const { return _origin; }
-+
-+#if !defined GRAPHITE2_NTRACING
-+	void outputJsonDbg(json * const dbgout, Segment *seg, int axis);
-+	void outputJsonDbgStartSlot(json * const dbgout, Segment *seg);
-+	void outputJsonDbgEndSlot(json * const dbgout, Position resultPos, int bestAxis, bool isCol);
-+	void outputJsonDbgOneVector(json * const dbgout, Segment *seg, int axis, float tleft, float bestCost, float bestVal);
-+	void outputJsonDbgRawRanges(json * const dbgout, int axis);
-+	void outputJsonDbgRemovals(json * const dbgout, int axis, Segment *seg);
-+#endif
-+
-+    CLASS_NEW_DELETE;
-+
-+protected:
-+    Zones _ranges[4];   // possible movements in 4 directions (horizontally, vertically, diagonally);
-+    Slot *  _target;    // the glyph to fix
-+    Rect    _limit;
-+    Position _currShift;
-+    Position _currOffset;
-+    Position _origin;   // Base for all relative calculations
-+    float   _margin;
-+	float	_marginWt;
-+    float   _len[4];
-+    uint16  _seqClass;
-+	uint16	_seqProxClass;
-+    uint16  _seqOrder;
-+    
-+	//bool _scraping[4];
-+
-+};	// end of class ShiftCollider
-+
-+inline
-+ShiftCollider::ShiftCollider(GR_MAYBE_UNUSED json *dbgout)
-+: _target(0),
-+  _margin(0.0),
-+  _marginWt(0.0),
-+  _seqClass(0),
-+  _seqProxClass(0),
-+  _seqOrder(0)
-+{
-+#if !defined GRAPHITE2_NTRACING
-+    for (int i = 0; i < 4; ++i)
-+        _ranges[i].setdebug(dbgout);
-+#endif
-+}
-+
-+class KernCollider
-+{
-+public:
-+    KernCollider(json *dbg);
-+    ~KernCollider() throw() { };
-+    bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint, float margin,
-+            const Position &currShift, const Position &offsetPrev, int dir,
-+            float ymin, float ymax, json * const dbgout);
-+    bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, json * const dbgout);
-+    Position resolve(Segment *seg, Slot *slot, int dir, float margin, json * const dbgout);
-+    void shift(const Position &mv, int dir);
-+
-+    CLASS_NEW_DELETE;
-+
-+private:
-+    Slot *  _target;        // the glyph to fix
-+    Rect    _limit;
-+    float   _margin;
-+    Position _offsetPrev;   // kern from a previous pass
-+    Position _currShift;    // NOT USED??
-+    float _miny;	        // y-coordinates offset by global slot position
-+    float _maxy;
-+    Vector<float> _edges;   // edges of horizontal slices
-+    float _sliceWidth;      // width of each slice
-+    float _mingap;
-+    float _xbound;        // max or min edge
-+
-+#if !defined GRAPHITE2_NTRACING    
-+    // Debugging
-+    Segment * _seg;
-+    Vector<float> _nearEdges; // closest potential collision in each slice
-+    Vector<Slot*> _slotNear;
-+#endif
-+};	// end of class KernCollider
-+
-+
-+inline
-+float sqr(float x) {
-+    return x * x;
-+}
-+
-+inline
-+KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
-+: _target(0),
-+  _margin(0.0f),
-+  _miny(-1e38f),
-+  _maxy(1e38f),
-+  _sliceWidth(0.0f),
-+  _mingap(0.0f),
-+  _xbound(0.0)
-+{
-+#if !defined GRAPHITE2_NTRACING
-+    _seg = 0;
-+#endif
-+};
-+
-+};  // end of namespace graphite2
-+
-diff --git a/gfx/graphite2/src/inc/Compression.h b/gfx/graphite2/src/inc/Compression.h
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/inc/Compression.h
-@@ -0,0 +1,103 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2015, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+
-+#pragma once
-+
-+#include <cassert>
-+#include <cstddef>
-+#include <cstring>
-+
-+namespace
-+{
-+
-+#if defined(_MSC_VER)
-+typedef unsigned __int8 u8;
-+typedef unsigned __int16 u16;
-+typedef unsigned __int32 u32;
-+typedef unsigned __int64 u64;
-+#else
-+#include <stdint.h>
-+typedef uint8_t u8;
-+typedef uint16_t u16;
-+typedef uint32_t u32;
-+typedef uint64_t u64;
-+#endif
-+
-+ptrdiff_t const     MINMATCH  = 4;
-+
-+template<int S>
-+inline 
-+void unaligned_copy(void * d, void const * s) {
-+  ::memcpy(d, s, S);
-+}
-+
-+inline
-+size_t align(size_t p) {
-+    return (p + sizeof(unsigned long)-1) & ~(sizeof(unsigned long)-1);
-+}
-+
-+inline 
-+u8 * safe_copy(u8 * d, u8 const * s, size_t n) {
-+    while (n--) *d++ = *s++;
-+    return d;
-+}
-+
-+inline
-+u8 * overrun_copy(u8 * d, u8 const * s, size_t n) {
-+    size_t const WS = sizeof(unsigned long);
-+    u8 const * e = s + n;
-+    do 
-+    {
-+        unaligned_copy<WS>(d, s);
-+        d += WS;
-+        s += WS;
-+    }
-+    while (s < e);
-+    d-=(s-e);
-+    
-+    return d;
-+}
-+
-+
-+inline
-+u8 * fast_copy(u8 * d, u8 const * s, size_t n) {
-+    size_t const WS = sizeof(unsigned long);
-+    size_t wn = n/WS;
-+    while (wn--) 
-+    {
-+        unaligned_copy<WS>(d, s);
-+        d += WS;
-+        s += WS;
-+    }
-+    n &= WS-1;
-+    return safe_copy(d, s, n);
-+}
-+
-+
-+} // end of anonymous namespace
-+
-+
-diff --git a/gfx/graphite2/src/inc/Decompressor.h b/gfx/graphite2/src/inc/Decompressor.h
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/inc/Decompressor.h
-@@ -0,0 +1,56 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2015, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+
-+#pragma once
-+
-+#include <cstddef>
-+
-+namespace lz4
-+{
-+
-+// decompress an LZ4 block
-+// Parameters:
-+//      @in         -   Input buffer containing an LZ4 block.
-+//      @in_size    -   Size of the input LZ4 block in bytes.
-+//      @out        -   Output buffer to hold decompressed results.
-+//      @out_size   -   The size of the buffer pointed to by @out.
-+// Invariants:
-+//      @in         -   This buffer must be at least 1 machine word in length,
-+//                      regardless of the actual LZ4 block size.
-+//      @in_size    -   This must be at least 4 and must also be <= to the
-+//                      allocated buffer @in.
-+//      @out        -   This must be bigger than the input buffer and at least
-+//                      13 bytes.
-+//      @out_size   -   Must always be big enough to hold the expected size.
-+// Return:
-+//      -1          -  Decompression failed.
-+//      size        -  Actual number of bytes decompressed.
-+int decompress(void const *in, size_t in_size, void *out, size_t out_size);
-+
-+} // end of namespace shrinker
-+
-+
-diff --git a/gfx/graphite2/src/inc/Error.h b/gfx/graphite2/src/inc/Error.h
---- a/gfx/graphite2/src/inc/Error.h
-+++ b/gfx/graphite2/src/inc/Error.h
-@@ -106,22 +106,30 @@ enum errors {
-     E_BADRULECCODEPTR = 45, // The rule constraint code position does not align with where the forward reference says it should be
-     E_BADCCODELEN = 46,     // Bad rule/pass constraint code length
-     E_BADACTIONCODEPTR = 47,    // The action code position does not align with where the forward reference says it should be
-     E_MUTABLECCODE = 48,    // Constraint code edits slots. It shouldn't.
-     E_BADSTATE = 49,        // Bad state transition referencing an illegal state
-     E_BADRULEMAPPING = 50,  // The structure of the rule mapping is bad
-     E_BADRANGE = 51,        // Bad column range structure including a glyph in more than one column
-     E_BADRULENUM = 52,      // A reference to a rule is out of range (too high)
-+    E_BADACOLLISION = 53,   // Bad Silf table collision attribute number (too high)
-+    E_BADEMPTYPASS = 54,    // Can't have empty passes (no rules) except for collision passes
-+    E_BADSILFVERSION = 55,  // The Silf table has a bad version (probably too high)
-+    E_BADCOLLISIONPASS = 56,    // Collision flags set on a non positioning pass
-+    E_BADNUMCOLUMNS = 57,   // Arbitrarily limit number of columns in fsm
- // Code errors
-     E_CODEFAILURE = 60,     // Base code error. The following subcodes must align with Machine::Code::status_t in Code.h
--        E_CODEALLOC = 61,       // Out of memory
--        E_INVALIDOPCODE = 62,   // Invalid op code
--        E_UNIMPOPCODE = 63,     // Unimplemented op code encountered
--        E_OUTOFRANGECODE = 64,  // Code argument out of range
--        E_BADJUMPCODE = 65,     // Code jumps past end of op codes
--        E_CODEBADARGS = 66,     // Code arguments exhausted
--        E_CODENORETURN = 67,    // Missing return type op code at end of code
--        E_CODENESTEDCTXT = 68   // Nested context encountered in code
-+    E_CODEALLOC = 61,       // Out of memory
-+    E_INVALIDOPCODE = 62,   // Invalid op code
-+    E_UNIMPOPCODE = 63,     // Unimplemented op code encountered
-+    E_OUTOFRANGECODE = 64,  // Code argument out of range
-+    E_BADJUMPCODE = 65,     // Code jumps past end of op codes
-+    E_CODEBADARGS = 66,     // Code arguments exhausted
-+    E_CODENORETURN = 67,    // Missing return type op code at end of code
-+    E_CODENESTEDCTXT = 68,   // Nested context encountered in code
-+// Compression errors
-+    E_BADSCHEME = 69,
-+    E_SHRINKERFAILED = 70,
- };
- 
- }
- 
-diff --git a/gfx/graphite2/src/inc/Face.h b/gfx/graphite2/src/inc/Face.h
---- a/gfx/graphite2/src/inc/Face.h
-+++ b/gfx/graphite2/src/inc/Face.h
-@@ -21,33 +21,34 @@
- 
- Alternatively, the contents of this file may be used under the terms of the
- Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
- #pragma once
- 
--#include <stdio.h>
-+#include <cstdio>
- 
- #include "graphite2/Font.h"
- 
- #include "inc/Main.h"
- #include "inc/FeatureMap.h"
- #include "inc/TtfUtil.h"
- #include "inc/Silf.h"
- #include "inc/Error.h"
- 
- namespace graphite2 {
- 
- class Cmap;
- class FileFace;
- class GlyphCache;
- class NameTable;
- class json;
-+class Font;
- 
- 
- using TtfUtil::Tag;
- 
- // These are the actual tags, as distinct from the consecutive IDs in TtfUtil.h
- 
- class Face
- {
-@@ -165,47 +166,51 @@ json * Face::logger() const throw()
- 
- 
- 
- class Face::Table
- {
-     const Face *            _f;
-     mutable const byte *    _p;
-     uint32                  _sz;
-+    bool                    _compressed;
-+
-+    Error decompress();
-+
-+    void releaseBuffers();
- 
- public:
-     Table() throw();
--    Table(const Face & face, const Tag n) throw();
-+    Table(const Face & face, const Tag n, uint32 version=0xffffffff) throw();
-     Table(const Table & rhs) throw();
-     ~Table() throw();
- 
-     operator const byte * () const throw();
- 
-     Table & operator = (const Table & rhs) throw();
-     size_t  size() const throw();
- };
- 
- inline
- Face::Table::Table() throw()
--: _f(0), _p(0), _sz(0)
-+: _f(0), _p(0), _sz(0), _compressed(false)
- {
- }
- 
- inline
- Face::Table::Table(const Table & rhs) throw()
--: _f(rhs._f), _p(rhs._p), _sz(rhs._sz)
-+: _f(rhs._f), _p(rhs._p), _sz(rhs._sz), _compressed(rhs._compressed)
- {
-     rhs._p = 0;
- }
- 
- inline
- Face::Table::~Table() throw()
- {
--    if (_p && _f->m_ops.release_table)
--        (*_f->m_ops.release_table)(_f->m_appFaceHandle, _p);
-+    releaseBuffers();
- }
- 
- inline
- Face::Table::operator const byte * () const throw()
- {
-     return _p;
- }
- 
-diff --git a/gfx/graphite2/src/inc/FeatureMap.h b/gfx/graphite2/src/inc/FeatureMap.h
---- a/gfx/graphite2/src/inc/FeatureMap.h
-+++ b/gfx/graphite2/src/inc/FeatureMap.h
-@@ -51,17 +51,17 @@ private:
- };
- 
- class FeatureRef
- {
-     typedef uint32      chunk_t;
-     static const uint8  SIZEOF_CHUNK = sizeof(chunk_t)*8;
- 
- public:
--    FeatureRef() : m_nameValues(0) {}
-+    FeatureRef();
-     FeatureRef(const Face & face, unsigned short & bits_offset, uint32 max_val,
-                uint32 name, uint16 uiName, uint16 flags,
-                FeatureSetting *settings, uint16 num_set) throw();
-     ~FeatureRef() throw();
- 
-     bool applyValToFeature(uint32 val, Features& pDest) const; //defined in GrFaceImp.h
-     void maskFeature(Features & pDest) const {
-     if (m_index < pDest.size())                 //defensive
-@@ -94,16 +94,26 @@ private:
-     byte    m_bits,             // how many bits to shift the value into place
-             m_index;            // index into the array to find the ulong to mask
- 
- private:        //unimplemented
-     FeatureRef& operator=(const FeatureRef&);
- };
- 
- 
-+inline
-+FeatureRef::FeatureRef()
-+: m_pFace(0), m_nameValues(0),
-+  m_mask(0), m_max(0), m_id(0),
-+  m_nameid(0), m_flags(0), m_numSet(0),
-+  m_bits(0), m_index(0)
-+{
-+}
-+
-+
- class NameAndFeatureRef
- {
-   public:
-     NameAndFeatureRef(uint32 name = 0) : m_name(name) , m_pFRef(NULL){}
-     NameAndFeatureRef(const FeatureRef* p/*not NULL*/) : m_name(p->getId()), m_pFRef(p) {}
- 
-     bool operator<(const NameAndFeatureRef& rhs) const //orders by m_name
-         {   return m_name<rhs.m_name; }
-@@ -112,35 +122,34 @@ class NameAndFeatureRef
-  
-     uint32 m_name;
-     const FeatureRef* m_pFRef;
- };
- 
- class FeatureMap
- {
- public:
--    FeatureMap() : m_numFeats(0), m_feats(NULL), m_pNamedFeats(NULL),
--        m_defaultFeatures(NULL) {}
--    ~FeatureMap() { delete [] m_feats; delete[] m_pNamedFeats; delete m_defaultFeatures; }
-+    FeatureMap() : m_numFeats(0), m_feats(NULL), m_pNamedFeats(NULL) {}
-+    ~FeatureMap() { delete [] m_feats; delete[] m_pNamedFeats; }
- 
-     bool readFeats(const Face & face);
-     const FeatureRef *findFeatureRef(uint32 name) const;
-     FeatureRef *feature(uint16 index) const { return m_feats + index; }
-     //GrFeatureRef *featureRef(byte index) { return index < m_numFeats ? m_feats + index : NULL; }
-     const FeatureRef *featureRef(byte index) const { return index < m_numFeats ? m_feats + index : NULL; }
-     FeatureVal* cloneFeatures(uint32 langname/*0 means default*/) const;      //call destroy_Features when done.
-     uint16 numFeats() const { return m_numFeats; };
-     CLASS_NEW_DELETE
- private:
- friend class SillMap;
-     uint16 m_numFeats;
- 
-     FeatureRef *m_feats;
-     NameAndFeatureRef* m_pNamedFeats;   //owned
--    FeatureVal* m_defaultFeatures;        //owned
-+    FeatureVal m_defaultFeatures;        //owned
-     
- private:        //defensive on m_feats, m_pNamedFeats, and m_defaultFeatures
-     FeatureMap(const FeatureMap&);
-     FeatureMap& operator=(const FeatureMap&);
- };
- 
- 
- class SillMap
-diff --git a/gfx/graphite2/src/inc/FileFace.h b/gfx/graphite2/src/inc/FileFace.h
---- a/gfx/graphite2/src/inc/FileFace.h
-+++ b/gfx/graphite2/src/inc/FileFace.h
-@@ -27,17 +27,17 @@ of the License or (at your option) any l
- #pragma once
- 
- //#include "inc/FeatureMap.h"
- //#include "inc/GlyphsCache.h"
- //#include "inc/Silf.h"
- 
- #ifndef GRAPHITE2_NFILEFACE
- 
--#include <stdio.h>
-+#include <cstdio>
- #include <cassert>
- 
- #include "graphite2/Font.h"
- 
- #include "inc/Main.h"
- #include "inc/TtfTypes.h"
- #include "inc/TtfUtil.h"
- 
-diff --git a/gfx/graphite2/src/inc/GlyphCache.h b/gfx/graphite2/src/inc/GlyphCache.h
---- a/gfx/graphite2/src/inc/GlyphCache.h
-+++ b/gfx/graphite2/src/inc/GlyphCache.h
-@@ -24,24 +24,73 @@ Mozilla Public License (http://mozilla.o
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
- #pragma once
- 
- 
- #include "graphite2/Font.h"
- #include "inc/Main.h"
-+#include "inc/Position.h"
-+#include "inc/GlyphFace.h"
- 
- namespace graphite2 {
- 
- class Face;
- class FeatureVal;
--class GlyphFace;
- class Segment;
- 
-+
-+struct SlantBox
-+{
-+    static const SlantBox empty;
-+
-+//    SlantBox(float psi = 0., float pdi = 0., float psa = 0., float pda = 0.) : si(psi), di(pdi), sa(psa), da(pda) {};
-+    float width() const { return sa - si; }
-+    float height() const { return da - di; }
-+    float si; // min
-+    float di; // min
-+    float sa; // max
-+    float da; // max
-+};
-+
-+
-+struct BBox
-+{
-+    BBox(float pxi = 0, float pyi = 0., float pxa = 0., float pya = 0.) : xi(pxi), yi(pyi), xa(pxa), ya(pya) {};
-+    float width() const { return xa - xi; }
-+    float height() const { return ya - yi; }
-+    float xi; // min
-+    float yi; // min
-+    float xa; // max
-+    float ya; // max
-+};
-+
-+
-+class GlyphBox
-+{
-+    GlyphBox(const GlyphBox &);
-+    GlyphBox & operator = (const GlyphBox &);
-+
-+public:
-+    GlyphBox(uint8 numsubs, unsigned short bitmap, Rect *slanted) : _num(numsubs), _bitmap(bitmap), _slant(*slanted) {}; 
-+
-+    void addSubBox(int subindex, int boundary, Rect *val) { _subs[subindex * 2 + boundary] = *val; }
-+    Rect &subVal(int subindex, int boundary) { return _subs[subindex * 2 + boundary]; }
-+    const Rect &slant() const { return _slant; }
-+    uint8 num() const { return _num; }
-+    const Rect *subs() const { return _subs; }
-+
-+private:
-+    uint8   _num;
-+    unsigned short  _bitmap;
-+    Rect    _slant;
-+    Rect    _subs[1];
-+};
-+
- class GlyphCache
- {
-     class Loader;
- 
-     GlyphCache(const GlyphCache&);
-     GlyphCache& operator=(const GlyphCache&);
- 
- public:
-@@ -49,22 +98,34 @@ public:
-     ~GlyphCache();
- 
-     unsigned short  numGlyphs() const throw();
-     unsigned short  numAttrs() const throw();
-     unsigned short  unitsPerEm() const throw();
- 
-     const GlyphFace *glyph(unsigned short glyphid) const;      //result may be changed by subsequent call with a different glyphid
-     const GlyphFace *glyphSafe(unsigned short glyphid) const;
-+    float            getBoundingMetric(unsigned short glyphid, uint8 metric) const;
-+    uint8            numSubBounds(unsigned short glyphid) const;
-+    float            getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const;
-+    const Rect &     slant(unsigned short glyphid) const { return _boxes[glyphid] ? _boxes[glyphid]->slant() : _empty_slant_box; }
-+    const SlantBox & getBoundingSlantBox(unsigned short glyphid) const;
-+    const BBox &     getBoundingBBox(unsigned short glyphid) const;
-+    const SlantBox & getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const;
-+    const BBox &     getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const;
-+    bool             check(unsigned short glyphid) const;
-+    bool             hasBoxes() const { return _boxes != 0; }
- 
-     CLASS_NEW_DELETE;
-     
- private:
-+    const Rect            _empty_slant_box;
-     const Loader        * _glyph_loader;
-     const GlyphFace *   * _glyphs;
-+    GlyphBox        *   * _boxes;
-     unsigned short        _num_glyphs,
-                           _num_attrs,
-                           _upem;
- };
- 
- inline
- unsigned short GlyphCache::numGlyphs() const throw()
- {
-@@ -79,14 +140,84 @@ unsigned short GlyphCache::numAttrs() co
- 
- inline
- unsigned short  GlyphCache::unitsPerEm() const throw()
- {
-     return _upem;
- }
- 
- inline
-+bool GlyphCache::check(unsigned short glyphid) const
-+{
-+    return _boxes && glyphid < _num_glyphs;
-+}
-+
-+inline
- const GlyphFace *GlyphCache::glyphSafe(unsigned short glyphid) const
- {
-     return glyphid < _num_glyphs ? glyph(glyphid) : NULL;
- }
- 
-+inline
-+float GlyphCache::getBoundingMetric(unsigned short glyphid, uint8 metric) const
-+{
-+    if (glyphid >= _num_glyphs) return 0.;
-+    switch (metric) {
-+        case 0: return (float)(glyph(glyphid)->theBBox().bl.x);                          // x_min
-+        case 1: return (float)(glyph(glyphid)->theBBox().bl.y);                          // y_min
-+        case 2: return (float)(glyph(glyphid)->theBBox().tr.x);                          // x_max
-+        case 3: return (float)(glyph(glyphid)->theBBox().tr.y);                          // y_max
-+        case 4: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.x : 0.f);    // sum_min
-+        case 5: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().bl.y : 0.f);    // diff_min
-+        case 6: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.x : 0.f);    // sum_max
-+        case 7: return (float)(_boxes[glyphid] ? _boxes[glyphid]->slant().tr.y : 0.f);    // diff_max
-+        default: return 0.;
-+    }
-+}
-+
-+inline const SlantBox &GlyphCache::getBoundingSlantBox(unsigned short glyphid) const
-+{
-+    return _boxes[glyphid] ? *(SlantBox *)(&(_boxes[glyphid]->slant())) : SlantBox::empty;
-+}
-+
-+inline const BBox &GlyphCache::getBoundingBBox(unsigned short glyphid) const
-+{
-+    return *(BBox *)(&(glyph(glyphid)->theBBox()));
-+}
-+
-+inline
-+float GlyphCache::getSubBoundingMetric(unsigned short glyphid, uint8 subindex, uint8 metric) const
-+{
-+    GlyphBox *b = _boxes[glyphid];
-+    if (b == NULL || subindex >= b->num()) return 0;
-+
-+    switch (metric) {
-+        case 0: return b->subVal(subindex, 0).bl.x;
-+        case 1: return b->subVal(subindex, 0).bl.y;
-+        case 2: return b->subVal(subindex, 0).tr.x;
-+        case 3: return b->subVal(subindex, 0).tr.y;
-+        case 4: return b->subVal(subindex, 1).bl.x;
-+        case 5: return b->subVal(subindex, 1).bl.y;
-+        case 6: return b->subVal(subindex, 1).tr.x;
-+        case 7: return b->subVal(subindex, 1).tr.y;
-+        default: return 0.;
-+    }
-+}
-+
-+inline const SlantBox &GlyphCache::getSubBoundingSlantBox(unsigned short glyphid, uint8 subindex) const
-+{
-+    GlyphBox *b = _boxes[glyphid];
-+    return *(SlantBox *)(b->subs() + 2 * subindex + 1);
-+}
-+
-+inline const BBox &GlyphCache::getSubBoundingBBox(unsigned short glyphid, uint8 subindex) const
-+{
-+    GlyphBox *b = _boxes[glyphid];
-+    return *(BBox *)(b->subs() + 2 * subindex);
-+}
-+
-+inline
-+uint8 GlyphCache::numSubBounds(unsigned short glyphid) const
-+{
-+    return _boxes[glyphid] ? _boxes[glyphid]->num() : 0;
-+}
-+
- } // namespace graphite2
-diff --git a/gfx/graphite2/src/inc/Intervals.h b/gfx/graphite2/src/inc/Intervals.h
-new file mode 100644
---- /dev/null
-+++ b/gfx/graphite2/src/inc/Intervals.h
-@@ -0,0 +1,234 @@
-+/*  GRAPHITE2 LICENSING
-+
-+    Copyright 2010, SIL International
-+    All rights reserved.
-+
-+    This library is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU Lesser General Public License as published
-+    by the Free Software Foundation; either version 2.1 of License, or
-+    (at your option) any later version.
-+
-+    This program 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
-+    Lesser General Public License for more details.
-+
-+    You should also have received a copy of the GNU Lesser General Public
-+    License along with this library in the file named "LICENSE".
-+    If not, write to the Free Software Foundation, 51 Franklin Street, 
-+    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
-+    internet at http://www.fsf.org/licenses/lgpl.html.
-+
-+Alternatively, the contents of this file may be used under the terms of the
-+Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
-+License, as published by the Free Software Foundation, either version 2
-+of the License or (at your option) any later version.
-+*/
-+#pragma once
-+
-+#include <utility>
-+
-+#include "inc/Main.h"
-+#include "inc/List.h"
-+#include "inc/json.h"
-+#include "inc/Position.h"
-+
-+// An IntervalSet represents the possible movement of a given glyph in a given direction
-+// (horizontally, vertically, or diagonally).
-+// A vector is needed to represent disjoint ranges, eg, -300..-150, 20..200, 500..750.
-+// Each pair represents the min/max of a sub-range.
-+
-+namespace graphite2 {
-+
-+class Segment;
-+
-+enum zones_t {SD, XY};
-+
-+class Zones
-+{
-+    struct Exclusion
-+    {
-+        template<zones_t O>
-+        static Exclusion weighted(float xmin, float xmax, float f, float a0,
-+                float m, float xi, float ai, float c, bool nega);
-+
-+        float   x,  // x position
-+                xm, // xmax position
-+                c,  // constant + sum(MiXi^2)
-+                sm, // sum(Mi)
-+                smx; // sum(MiXi)
-+        bool    open;
-+
-+        Exclusion(float x, float w, float smi, float smxi, float c);
-+        Exclusion & operator += (Exclusion const & rhs);
-+        uint8 outcode(float p) const;
-+
-+        Exclusion   split_at(float p);
-+        void        left_trim(float p);
-+
-+        bool        track_cost(float & cost, float & x, float origin) const;
-+
-+    private:
-+        float test_position(float origin) const;
-+        float cost(float x) const;
-+     };
-+
-+    typedef Vector<Exclusion>                   exclusions;
-+
-+    typedef exclusions::iterator                iterator;
-+    typedef Exclusion *                         pointer;
-+    typedef Exclusion &                         reference;
-+    typedef std::reverse_iterator<iterator>     reverse_iterator;
-+
-+public:
-+    typedef exclusions::const_iterator              const_iterator;
-+    typedef Exclusion const *                       const_pointer;
-+    typedef Exclusion const &                       const_reference;
-+    typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
-+
-+#if !defined GRAPHITE2_NTRACING
-+    struct Debug
-+    {
-+        Exclusion       _excl;
-+        bool            _isdel;
-+        Vector<void *>  _env;
-+
-+        Debug(Exclusion *e, bool isdel, json *dbg) : _excl(*e), _isdel(isdel), _env(dbg->getenvs()) { };
-+    };
-+
-+    typedef Vector<Debug>                       debugs;
-+    typedef debugs::const_iterator                    idebugs;
-+    void addDebug(Exclusion *e);
-+    void removeDebug(float pos, float posm);
-+    void setdebug(json *dbgout) { _dbg = dbgout; }
-+    idebugs dbgs_begin() const { return _dbgs.begin(); }
-+    idebugs dbgs_end() const { return _dbgs.end(); }
-+    void jsonDbgOut(Segment *seg) const;
-+    Position position() const { return Position(_pos, _posm); }
-+#endif
-+
-+    Zones();
-+    template<zones_t O>
-+    void initialise(float xmin, float xmax, float margin_len, float margin_weight, float ao);
-+
-+    void exclude(float xmin, float xmax);
-+    void exclude_with_margins(float xmin, float xmax, int axis);
-+
-+    template<zones_t O>
-+    void weighted(float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega);
-+    void weightedAxis(int axis, float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega);
-+
-+    float closest( float origin, float &cost) const;
-+
-+    const_iterator begin() const { return _exclusions.begin(); }
-+    const_iterator end() const { return _exclusions.end(); }
-+
-+private:
-+    exclusions  _exclusions;
-+#if !defined GRAPHITE2_NTRACING
-+    json      * _dbg;
-+    debugs      _dbgs;
-+#endif
-+    float       _margin_len,
-+                _margin_weight,
-+                _pos,
-+                _posm;
-+
-+    void            insert(Exclusion e);
-+    void            remove(float x, float xm);
-+    const_iterator  find_exclusion_under(float x) const;
-+};
-+
-+
-+inline
-+Zones::Zones()
-+: _margin_len(0), _margin_weight(0), _pos(0), _posm(0)
-+{
-+#if !defined GRAPHITE2_NTRACING
-+    _dbg = 0;
-+#endif
-+    _exclusions.reserve(8);
-+}
-+
-+inline
-+Zones::Exclusion::Exclusion(float x_, float xm_, float smi, float smxi, float c_)
-+: x(x_), xm(xm_), c(c_), sm(smi), smx(smxi), open(false)
-+{ }
-+
-+template<zones_t O>
-+inline
-+void Zones::initialise(float xmin, float xmax, float margin_len,
-+        float margin_weight, float a0)
-+{
-+    _margin_len = margin_len;
-+    _margin_weight = margin_weight;
-+    _pos = xmin;
-+    _posm = xmax;
-+    _exclusions.clear();
-+    _exclusions.push_back(Exclusion::weighted<O>(xmin, xmax, 1, a0, 0, 0, 0, 0, false));
-+    _exclusions.front().open = true;
-+#if !defined GRAPHITE2_NTRACING
-+    _dbgs.clear();
-+#endif
-+}
-+
-+inline
-+void Zones::exclude(float xmin, float xmax) {
-+    remove(xmin, xmax);
-+}
-+
-+template<zones_t O>
-+inline
-+void Zones::weighted(float xmin, float xmax, float f, float a0,
-+        float m, float xi, float ai, float c, bool nega) {
-+    insert(Exclusion::weighted<O>(xmin, xmax, f, a0, m, xi, ai, c, nega));
-+}
-+
-+inline
-+void Zones::weightedAxis(int axis, float xmin, float xmax, float f, float a0,
-+        float m, float xi, float ai, float c, bool nega) {
-+    if (axis < 2)
-+        weighted<XY>(xmin, xmax, f, a0, m, xi, ai, c, nega);
-+    else
-+        weighted<SD>(xmin, xmax, f, a0, m, xi, ai, c, nega);
-+}
-+
-+#if !defined GRAPHITE2_NTRACING
-+inline
-+void Zones::addDebug(Exclusion *e) {
-+    if (_dbg)
-+        _dbgs.push_back(Debug(e, false, _dbg));
-+}
-+
-+inline
-+void Zones::removeDebug(float pos, float posm) {
-+    if (_dbg)
-+    {
-+        Exclusion e(pos, posm, 0, 0, 0);
-+        _dbgs.push_back(Debug(&e, true, _dbg));
-+    }
-+}
-+#endif
-+
-+template<>
-+inline
-+Zones::Exclusion Zones::Exclusion::weighted<XY>(float xmin, float xmax, float f, float a0,
-+        float m, float xi, GR_MAYBE_UNUSED float ai, float c, GR_MAYBE_UNUSED bool nega) {
-+    return Exclusion(xmin, xmax,
-+            m + f,
-+            m * xi, 
-+            m * xi * xi + f * a0 * a0 + c);
-+}
-+
-+template<>
-+inline
-+Zones::Exclusion Zones::Exclusion::weighted<SD>(float xmin, float xmax, float f, float a0,
-+        float m, float xi, float ai,float c, bool nega) {
-+    float xia = nega ? xi - ai : xi + ai;
-+    return Exclusion(xmin, xmax, 
-+            0.25f * (m + 2.f * f), 
-+            0.25f * m * xia, 
-+            0.25f * (m * xia * xia + 2.f * f * a0 * a0) + c);
-+}
-+
-+} // end of namespace graphite2
-diff --git a/gfx/graphite2/src/inc/List.h b/gfx/graphite2/src/inc/List.h
---- a/gfx/graphite2/src/inc/List.h
-+++ b/gfx/graphite2/src/inc/List.h
-@@ -65,29 +65,30 @@ public:
-     iterator            end()           { return m_last; }
-     const_iterator      end() const     { return m_last; }
-     
-     bool                empty() const   { return m_first == m_last; }
-     size_t              size() const    { return m_last - m_first; }
-     size_t              capacity() const{ return m_end - m_first; }
-     
-     void                reserve(size_t n);
-+    void                resize(size_t n, const T & v = T());
-     
-     reference           front()         { assert(size() > 0); return *begin(); }
-     const_reference     front() const   { assert(size() > 0); return *begin(); }
-     reference           back()          { assert(size() > 0); return *(end()-1); }
-     const_reference     back() const    { assert(size() > 0); return *(end()-1); }
-     
-     Vector<T>         & operator = (const Vector<T> & rhs) { assign(rhs.begin(), rhs.end()); return *this; }
-     reference           operator [] (size_t n)          { assert(size() > n); return m_first[n]; }
-     const_reference     operator [] (size_t n) const    { assert(size() > n); return m_first[n]; }
-     
-     void                assign(size_t n, const T& u)    { clear(); insert(begin(), n, u); }
-     void                assign(const_iterator first, const_iterator last)      { clear(); insert(begin(), first, last); }
--    iterator            insert(iterator p, const T & x) { p = _insert_default(p, 1); *p = x; return p; }
-+    iterator            insert(iterator p, const T & x) { p = _insert_default(p, 1); new (p) T(x); return p; }
-     void                insert(iterator p, size_t n, const T & x);
-     void                insert(iterator p, const_iterator first, const_iterator last);
-     void                pop_back()              { assert(size() > 0); --m_last; }
-     void                push_back(const T &v)   { if (m_last == m_end) reserve(size()+1); new (m_last++) T(v); }
- 
-     void                clear()                 { erase(begin(), end()); }
-     iterator            erase(iterator p)       { return erase(p, p+1); }
-     iterator            erase(iterator first, iterator last);
-@@ -99,28 +100,37 @@ private:
- template <typename T>
- inline 
- void Vector<T>::reserve(size_t n)
- {
-     if (n > capacity()) 
-     {
-         const ptrdiff_t sz = size();
-         m_first = static_cast<T*>(realloc(m_first, n*sizeof(T)));
-+        if (!m_first)   std::abort();
-         m_last  = m_first + sz;
-         m_end   = m_first + n;
-     }
- }
- 
-+template <typename T>
-+inline
-+void Vector<T>::resize(size_t n, const T & v) {
-+    const ptrdiff_t d = n-size();
-+    if (d < 0)      erase(end()+d, end());
-+    else if (d > 0) insert(end(), d, v);
-+}
-+
- template<typename T> 
- inline 
- typename Vector<T>::iterator Vector<T>::_insert_default(iterator p, size_t n)
- {
-     assert(begin() <= p && p <= end());
-     const ptrdiff_t i = p - begin();
--    reserve((size() + n + 7) >> 3 << 3);
-+    reserve(((size() + n + 7) >> 3) << 3);
-     p = begin() + i;
-     // Move tail if there is one
-     if (p != end()) memmove(p + n, p, distance(p,end())*sizeof(T));
-     m_last += n;
-     return p;
- }
- 
- template<typename T> 
-diff --git a/gfx/graphite2/src/inc/Machine.h b/gfx/graphite2/src/inc/Machine.h
---- a/gfx/graphite2/src/inc/Machine.h
-+++ b/gfx/graphite2/src/inc/Machine.h
-@@ -105,17 +105,19 @@ enum opcode {
- 
-     PUSH_IGLYPH_ATTR,    // not implemented
- 
-     POP_RET,                        RET_ZERO,           RET_TRUE,
-     IATTR_SET,                      IATTR_ADD,          IATTR_SUB,
-     PUSH_PROC_STATE,                PUSH_VERSION,
-     PUT_SUBS,                       PUT_SUBS2,          PUT_SUBS3,
-     PUT_GLYPH,                      PUSH_GLYPH_ATTR,    PUSH_ATT_TO_GLYPH_ATTR,
--    MAX_OPCODE,
-+    BITOR,                          BITAND,             BITNOT,
-+    BITSET,                         SET_FEAT,
-+    MAX_OPCODE,                     
-     // private opcodes for internal use only, comes after all other on disk opcodes
-     TEMP_COPY = MAX_OPCODE
- };
- 
- struct opcode_t 
- {
-     instr           impl[2];
-     uint8           param_sz;
-@@ -143,17 +145,17 @@ public:
- 
-     Machine(SlotMap &) throw();
-     static const opcode_t *   getOpcodeTable() throw();
- 
-     CLASS_NEW_DELETE;
- 
-     SlotMap   & slotMap() const throw();
-     status_t    status() const throw();
--    operator bool () const throw();
-+//    operator bool () const throw();
- 
- private:
-     void    check_final_stack(const stack_t * const sp);
-     stack_t run(const instr * program, const byte * data,
-                 slotref * & map) HOT;
- 
-     SlotMap       & _map;
-     stack_t         _stack[STACK_MAX + 2*STACK_GUARD];
-diff --git a/gfx/graphite2/src/inc/Main.h b/gfx/graphite2/src/inc/Main.h
---- a/gfx/graphite2/src/inc/Main.h
-+++ b/gfx/graphite2/src/inc/Main.h
-@@ -80,25 +80,25 @@ struct telemetry  {};
- // typesafe wrapper around malloc for simple types
- // use free(pointer) to deallocate
- 
- template <typename T> T * gralloc(size_t n)
- {
- #ifdef GRAPHITE2_TELEMETRY
-     telemetry::count_bytes(sizeof(T) * n);
- #endif
--    return reinterpret_cast<T*>(malloc(sizeof(T) * n));
-+    return static_cast<T*>(malloc(sizeof(T) * n));
- }
- 
- template <typename T> T * grzeroalloc(size_t n)
- {
- #ifdef GRAPHITE2_TELEMETRY
-     telemetry::count_bytes(sizeof(T) * n);
- #endif
--    return reinterpret_cast<T*>(calloc(n, sizeof(T)));
-+    return static_cast<T*>(calloc(n, sizeof(T)));
- }
- 
- template <typename T>
- inline T min(const T a, const T b)
- {
-     return a < b ? a : b;
- }
- 
-@@ -115,13 +115,32 @@ inline T max(const T a, const T b)
-     void * operator new   (size_t, void * p) throw() { return p; } \
-     void * operator new[] (size_t size) {return gralloc<byte>(size);} \
-     void * operator new[] (size_t, void * p) throw() { return p; } \
-     void operator delete   (void * p) throw() { free(p);} \
-     void operator delete   (void *, void *) throw() {} \
-     void operator delete[] (void * p)throw() { free(p); } \
-     void operator delete[] (void *, void *) throw() {}
- 
--#ifdef __GNUC__
-+#if defined(__GNUC__)  || defined(__clang__)
- #define GR_MAYBE_UNUSED __attribute__((unused))
- #else
- #define GR_MAYBE_UNUSED
- #endif
-+
-+#if defined(__clang__) && __cplusplus >= 201103L
-+   /* clang's fallthrough annotations are only available starting in C++11. */
-+    #define GR_FALLTHROUGH [[clang::fallthrough]]
-+#elif defined(_MSC_VER)
-+   /*
-+    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
-+    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
-+    */
-+    #include <sal.h>
-+    #define GR_FALLTHROUGH __fallthrough
-+#else
-+    #define GR_FALLTHROUGH /* fallthrough */
-+#endif
-+
-+#ifdef _MSC_VER
-+#pragma warning(disable: 4800)
-+#pragma warning(disable: 4355)
-+#endif
-diff --git a/gfx/graphite2/src/inc/Pass.h b/gfx/graphite2/src/inc/Pass.h
---- a/gfx/graphite2/src/inc/Pass.h
-+++ b/gfx/graphite2/src/inc/Pass.h
-@@ -34,65 +34,85 @@ namespace graphite2 {
- class Segment;
- class Face;
- class Silf;
- struct Rule;
- struct RuleEntry;
- struct State;
- class FiniteStateMachine;
- class Error;
-+class ShiftCollider;
-+class KernCollider;
-+class json;
-+
-+enum passtype;
- 
- class Pass
- {   
- public:
-     Pass();
-     ~Pass();
-     
--    bool readPass(const byte * pPass, size_t pass_length, size_t subtable_base, Face & face, Error &e);
--    void runGraphite(vm::Machine & m, FiniteStateMachine & fsm) const;
-+    bool readPass(const byte * pPass, size_t pass_length, size_t subtable_base, Face & face,
-+        enum passtype pt, uint32 version, Error &e);
-+    bool runGraphite(vm::Machine & m, FiniteStateMachine & fsm, bool reverse) const;
-     void init(Silf *silf) { m_silf = silf; }
--    byte spaceContextuals() const { return (m_flags & 0x0E) >> 1; }
-+    byte collisionLoops() const { return m_numCollRuns; }
-+    bool reverseDir() const { return m_isReverseDir; }
- 
-     CLASS_NEW_DELETE
- private:
-     void    findNDoRule(Slot* & iSlot, vm::Machine &, FiniteStateMachine& fsm) const;
-     int     doAction(const vm::Machine::Code* codeptr, Slot * & slot_out, vm::Machine &) const;
-     bool    testPassConstraint(vm::Machine & m) const;
-     bool    testConstraint(const Rule & r, vm::Machine &) const;
-     bool    readRules(const byte * rule_map, const size_t num_entries,
-                      const byte *precontext, const uint16 * sort_key,
-                      const uint16 * o_constraint, const byte *constraint_data, 
-                      const uint16 * o_action, const byte * action_data,
--                     Face &, Error &e);
-+                     Face &, enum passtype pt, Error &e);
-     bool    readStates(const byte * starts, const byte * states, const byte * o_rule_map, Face &, Error &e);
-     bool    readRanges(const byte * ranges, size_t num_ranges, Error &e);
-     uint16  glyphToCol(const uint16 gid) const;
-     bool    runFSM(FiniteStateMachine & fsm, Slot * slot) const;
-     void    dumpRuleEventConsidered(const FiniteStateMachine & fsm, const RuleEntry & re) const;
--    void    dumpRuleEventOutput(const FiniteStateMachine & fsm, const Rule & r, Slot * os) const;
-+    void    dumpRuleEventOutput(const FiniteStateMachine & fsm, vm::Machine & m, const Rule & r, Slot * os) const;
-     void    adjustSlot(int delta, Slot * & slot_out, SlotMap &) const;
--    const Silf* m_silf;
--    uint16    * m_cols;
--    Rule      * m_rules; // rules
--    RuleEntry * m_ruleMap;
--    uint16    * m_startStates; // prectxt length
--    uint16    * m_transitions;
--    State     * m_states;
--    
--    byte   m_flags;
-+    bool    collisionShift(Segment *seg, int dir, json * const dbgout) const;
-+    bool    collisionKern(Segment *seg, int dir, json * const dbgout) const;
-+    bool    collisionFinish(Segment *seg, GR_MAYBE_UNUSED json * const dbgout) const;
-+    bool    resolveCollisions(Segment *seg, Slot *slot, Slot *start, ShiftCollider &coll, bool isRev,
-+                     int dir, bool &moved, bool &hasCol, json * const dbgout) const;
-+    float   resolveKern(Segment *seg, Slot *slot, Slot *start, KernCollider &coll, int dir,
-+                     float &ymin, float &ymax, json *const dbgout) const;
-+
-+    const Silf        * m_silf;
-+    uint16            * m_cols;
-+    Rule              * m_rules; // rules
-+    RuleEntry         * m_ruleMap;
-+    uint16            * m_startStates; // prectxt length
-+    uint16            * m_transitions;
-+    State             * m_states;
-+    vm::Machine::Code * m_codes;
-+    byte              * m_progs;
-+
-+    byte   m_numCollRuns;
-+    byte   m_kernColls;
-     byte   m_iMaxLoop;
-     uint16 m_numGlyphs;
-     uint16 m_numRules;
-     uint16 m_numStates;
-     uint16 m_numTransition;
-     uint16 m_numSuccess;
-     uint16 m_successStart;
-     uint16 m_numColumns;
-     byte m_minPreCtxt;
-     byte m_maxPreCtxt;
-+    byte m_colThreshold;
-+    bool m_isReverseDir;
-     vm::Machine::Code m_cPConstraint;
-     
- private:        //defensive
-     Pass(const Pass&);
-     Pass& operator=(const Pass&);
- };
- 
- } // namespace graphite2
-diff --git a/gfx/graphite2/src/inc/Position.h b/gfx/graphite2/src/inc/Position.h
---- a/gfx/graphite2/src/inc/Position.h
-+++ b/gfx/graphite2/src/inc/Position.h
-@@ -45,15 +45,24 @@ public:
- 
- class Rect
- {
- public :
-     Rect() {}
-     Rect(const Position& botLeft, const Position& topRight): bl(botLeft), tr(topRight) {}
-     Rect widen(const Rect& other) { return Rect(Position(bl.x > other.bl.x ? other.bl.x : bl.x, bl.y > other.bl.y ? other.bl.y : bl.y), Position(tr.x > other.tr.x ? tr.x : other.tr.x, tr.y > other.tr.y ? tr.y : other.tr.y)); }
-     Rect operator + (const Position &a) const { return Rect(Position(bl.x + a.x, bl.y + a.y), Position(tr.x + a.x, tr.y + a.y)); }
-+    Rect operator - (const Position &a) const { return Rect(Position(bl.x - a.x, bl.y - a.y), Position(tr.x - a.x, tr.y - a.y)); }
-     Rect operator * (float m) const { return Rect(Position(bl.x, bl.y) * m, Position(tr.x, tr.y) * m); }
-+    float width() const { return tr.x - bl.x; }
-+    float height() const { return tr.y - bl.y; }
-+
-+    bool hitTest(Rect &other);
-+
-+    // returns Position(overlapx, overlapy) where overlap<0 if overlapping else positive)
-+    Position overlap(Position &offset, Rect &other, Position &otherOffset);
-+    //Position constrainedAvoid(Position &offset, Rect &box, Rect &sdbox, Position &other, Rect &obox, Rect &osdbox);
- 
-     Position bl;
-     Position tr;
- };
- 
- } // namespace graphite2
-diff --git a/gfx/graphite2/src/inc/Rule.h b/gfx/graphite2/src/inc/Rule.h
---- a/gfx/graphite2/src/inc/Rule.h
-+++ b/gfx/graphite2/src/inc/Rule.h
-@@ -36,30 +36,36 @@ struct Rule {
-   const vm::Machine::Code * constraint, 
-                  * action;
-   unsigned short   sort;
-   byte             preContext;
- #ifndef NDEBUG
-   uint16           rule_idx;
- #endif
- 
--  Rule() : constraint(0), action(0), sort(0), preContext(0) {}
--  ~Rule();
-+  Rule();
-+  ~Rule() {}
- 
-   CLASS_NEW_DELETE;
- 
- private:
-   Rule(const Rule &);
-   Rule & operator = (const Rule &);
- };
- 
--inline Rule::~Rule()
-+inline
-+Rule::Rule()
-+: constraint(0),
-+  action(0),
-+  sort(0),
-+  preContext(0)
- {
--  delete constraint;
--  delete action;
-+#ifndef NDEBUG
-+  rule_idx = 0;
-+#endif
- }
- 
- 
- struct RuleEntry
- {
-   const Rule   * rule;
- 
-   inline
-@@ -91,40 +97,43 @@ bool State::empty() const
-     return rules_end == rules;
- }
- 
- 
- class SlotMap
- {
- public:
-   enum {MAX_SLOTS=64};
--  SlotMap(Segment & seg);
-+  SlotMap(Segment & seg, uint8 direction);
-   
-   Slot       * * begin();
-   Slot       * * end();
-   size_t         size() const;
-   unsigned short context() const;
-   void           reset(Slot &, unsigned short);
-   
-   Slot * const & operator[](int n) const;
-   Slot       * & operator [] (int);
-   void           pushSlot(Slot * const slot);
--  void           collectGarbage();
-+  void           collectGarbage(Slot *& aSlot);
- 
-   Slot         * highwater() { return m_highwater; }
-   void           highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
-   bool           highpassed() const { return m_highpassed; }
-   void           highpassed(bool v) { m_highpassed = v; }
- 
-+  uint8          dir() const { return m_dir; }
-+
-   Segment &    segment;
- private:
-   Slot         * m_slot_map[MAX_SLOTS+1];
-   unsigned short m_size;
-   unsigned short m_precontext;
-   Slot         * m_highwater;
-+  uint8          m_dir;
-   bool           m_highpassed;
- };
- 
- 
- class FiniteStateMachine
- {
- public:
-   enum {MAX_RULES=128};
-@@ -228,18 +237,18 @@ void FiniteStateMachine::Rules::accumula
-       return;
-     }
-   }
-   while (rre != rrend && out != lrend) { *out++ = *rre++; }
-   m_end = out;
- }
- 
- inline
--SlotMap::SlotMap(Segment & seg)
--: segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_highpassed(false)
-+SlotMap::SlotMap(Segment & seg, uint8 direction)
-+: segment(seg), m_size(0), m_precontext(0), m_highwater(0), m_dir(direction), m_highpassed(false)
- {
-     m_slot_map[0] = 0;
- }
- 
- inline
- Slot * * SlotMap::begin()
- {
-   return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
-diff --git a/gfx/graphite2/src/inc/SegCache.h b/gfx/graphite2/src/inc/SegCache.h
---- a/gfx/graphite2/src/inc/SegCache.h
-+++ b/gfx/graphite2/src/inc/SegCache.h
-@@ -258,17 +258,17 @@ public:
- 
-     CLASS_NEW_DELETE
- private:
-     void freeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level);
-     void purgeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level,
-                     unsigned long long minAccessCount, unsigned long long oldAccessTime);
- 
-     uint16 m_prefixLength;
--    uint16 m_maxCachedSegLength;
-+//    uint16 m_maxCachedSegLength;
-     size_t m_segmentCount;
-     SegCachePrefixArray m_prefixes;
-     Features m_features;
-     mutable unsigned long long m_totalAccessCount;
-     mutable unsigned long long m_totalMisses;
-     float m_purgeFactor;
- };
- 
-diff --git a/gfx/graphite2/src/inc/Segment.h b/gfx/graphite2/src/inc/Segment.h
---- a/gfx/graphite2/src/inc/Segment.h
-+++ b/gfx/graphite2/src/inc/Segment.h
-@@ -30,29 +30,28 @@ of the License or (at your option) any l
- 
- #include <cassert>
- 
- #include "inc/CharInfo.h"
- #include "inc/Face.h"
- #include "inc/FeatureVal.h"
- #include "inc/GlyphCache.h"
- #include "inc/GlyphFace.h"
--//#include "inc/Silf.h"
- #include "inc/Slot.h"
- #include "inc/Position.h"
- #include "inc/List.h"
--#include "inc/Bidi.h"
-+#include "inc/Collider.h"
- 
- #define MAX_SEG_GROWTH_FACTOR  256
- 
- namespace graphite2 {
- 
- typedef Vector<Features>        FeatureList;
- typedef Vector<Slot *>          SlotRope;
--typedef Vector<int16 *>        AttributeRope;
-+typedef Vector<int16 *>         AttributeRope;
- typedef Vector<SlotJustify *>   JustifyRope;
- 
- #ifndef GRAPHITE2_NSEGCACHE
- class SegmentScopeState;
- #endif
- class Font;
- class Segment;
- class Silf;
-@@ -81,119 +80,151 @@ private:
- 
- class Segment
- {
-     // Prevent copying of any kind.
-     Segment(const Segment&);
-     Segment& operator=(const Segment&);
- 
- public:
-+
-+    enum {
-+        SEG_INITCOLLISIONS = 1,
-+        SEG_HASCOLLISIONS = 2
-+    };
-+
-     unsigned int slotCount() const { return m_numGlyphs; }      //one slot per glyph
-     void extendLength(int num) { m_numGlyphs += num; }
-     Position advance() const { return m_advance; }
-     bool runGraphite() { if (m_silf) return m_face->runGraphite(this, m_silf); else return true;};
-     void chooseSilf(uint32 script) { m_silf = m_face->chooseSilf(script); }
-     const Silf *silf() const { return m_silf; }
-     unsigned int charInfoCount() const { return m_numCharinfo; }
-     const CharInfo *charinfo(unsigned int index) const { return index < m_numCharinfo ? m_charinfo + index : NULL; }
-     CharInfo *charinfo(unsigned int index) { return index < m_numCharinfo ? m_charinfo + index : NULL; }
--    int8 dir() const { return m_dir; }
- 
-     Segment(unsigned int numchars, const Face* face, uint32 script, int dir);
-     ~Segment();
- #ifndef GRAPHITE2_NSEGCACHE
-     SegmentScopeState setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength);
-     void removeScope(SegmentScopeState & state);
-     void append(const Segment &other);
-     void splice(size_t offset, size_t length, Slot * const startSlot,
-             Slot * endSlot, const Slot * srcSlot,
-             const size_t numGlyphs);
- #endif
-+    uint8 flags() const { return m_flags; }
-+    void flags(uint8 f) { m_flags = f; }
-     Slot *first() { return m_first; }
-     void first(Slot *p) { m_first = p; }
-     Slot *last() { return m_last; }
-     void last(Slot *p) { m_last = p; }
-     void appendSlot(int i, int cid, int gid, int fid, size_t coffset);
-     Slot *newSlot();
-     void freeSlot(Slot *);
-     SlotJustify *newJustify();
-     void freeJustify(SlotJustify *aJustify);
--    Position positionSlots(const Font *font, Slot *first=0, Slot *last=0);
-+    Position positionSlots(const Font *font=0, Slot *first=0, Slot *last=0, bool isRtl = false, bool isFinal = true);
-     void associateChars(int offset, int num);
-     void linkClusters(Slot *first, Slot *last);
-     uint16 getClassGlyph(uint16 cid, uint16 offset) const { return m_silf->getClassGlyph(cid, offset); }
-     uint16 findClassIndex(uint16 cid, uint16 gid) const { return m_silf->findClassIndex(cid, gid); }
-     int addFeatures(const Features& feats) { m_feats.push_back(feats); return m_feats.size() - 1; }
-     uint32 getFeature(int index, uint8 findex) const { const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex); if (!pFR) return 0; else return pFR->getFeatureVal(m_feats[index]); }
-+    void setFeature(int index, uint8 findex, uint32 val) {
-+        const FeatureRef* pFR=m_face->theSill().theFeatureMap().featureRef(findex); 
-+        if (pFR)
-+        {
-+            if (val > pFR->maxVal()) val = pFR->maxVal();
-+            pFR->applyValToFeature(val, m_feats[index]);
-+        } }
-+    int8 dir() const { return m_dir; }
-     void dir(int8 val) { m_dir = val; }
-+    bool currdir() const { return ((m_dir >> 6) ^ m_dir) & 1; }
-     unsigned int passBits() const { return m_passBits; }
-     void mergePassBits(const unsigned int val) { m_passBits &= val; }
-     int16 glyphAttr(uint16 gid, uint16 gattr) const { const GlyphFace * p = m_face->glyphs().glyphSafe(gid); return p ? p->attrs()[gattr] : 0; }
--    int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const;
-+    int32 getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const;
-     float glyphAdvance(uint16 gid) const { return m_face->glyphs().glyph(gid)->theAdvance().x; }
-     const Rect &theGlyphBBoxTemporary(uint16 gid) const { return m_face->glyphs().glyph(gid)->theBBox(); }   //warning value may become invalid when another glyph is accessed
-     Slot *findRoot(Slot *is) const { return is->attachedTo() ? findRoot(is->attachedTo()) : is; }
-     int numAttrs() const { return m_silf->numUser(); }
-     int defaultOriginal() const { return m_defaultOriginal; }
-     const Face * getFace() const { return m_face; }
-     const Features & getFeatures(unsigned int /*charIndex*/) { assert(m_feats.size() == 1); return m_feats[0]; }
--    void bidiPass(uint8 aBidi, int paradir, uint8 aMirror);
-+    void bidiPass(int paradir, uint8 aMirror);
-+    int8 getSlotBidiClass(Slot *s) const;
-+    void doMirror(uint16 aMirror);
-     Slot *addLineEnd(Slot *nSlot);
-     void delLineEnd(Slot *s);
-     bool hasJustification() const { return m_justifies.size() != 0; }
-+    void reverseSlots();
- 
-     bool isWhitespace(const int cid) const;
--
-+    bool hasCollisionInfo() const { return (m_flags & SEG_HASCOLLISIONS); }
-+    SlotCollision *collisionInfo(const Slot *s) const { return m_collisions ? m_collisions + s->index() : 0; }
-     CLASS_NEW_DELETE
- 
- public:       //only used by: GrSegment* makeAndInitialize(const GrFont *font, const GrFace *face, uint32 script, const FeaturesHandle& pFeats/*must not be IsNull*/, encform enc, const void* pStart, size_t nChars, int dir);
-     bool read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void*pStart, size_t nChars);
--    void prepare_pos(const Font *font);
--    void finalise(const Font *font);
-+    void finalise(const Font *font, bool reverse=false);
-     float justify(Slot *pSlot, const Font *font, float width, enum justFlags flags, Slot *pFirst, Slot *pLast);
-+    bool initCollisions();
-   
- private:
-     Position        m_advance;          // whole segment advance
-     SlotRope        m_slots;            // Vector of slot buffers
-     AttributeRope   m_userAttrs;        // Vector of userAttrs buffers
-     JustifyRope     m_justifies;        // Slot justification info buffers
-     FeatureList     m_feats;            // feature settings referenced by charinfos in this segment
-     Slot          * m_freeSlots;        // linked list of free slots
-     SlotJustify   * m_freeJustifies;    // Slot justification blocks free list
-     CharInfo      * m_charinfo;         // character info, one per input character
-+    SlotCollision * m_collisions;
-     const Face    * m_face;             // GrFace
-     const Silf    * m_silf;
-     Slot          * m_first;            // first slot in segment
-     Slot          * m_last;             // last slot in segment
-     unsigned int    m_bufSize,          // how big a buffer to create when need more slots
-                     m_numGlyphs,
-                     m_numCharinfo,      // size of the array and number of input characters
-                     m_passBits;         // if bit set then skip pass
-     int             m_defaultOriginal;  // number of whitespace chars in the string
-     int8            m_dir;
-+    uint8           m_flags;            // General purpose flags
- };
- 
--
-+inline
-+int8 Segment::getSlotBidiClass(Slot *s) const
-+{
-+    int8 res = s->getBidiClass();
-+    if (res != -1) return res;
-+    res = int8(glyphAttr(s->gid(), m_silf->aBidi()));
-+    s->setBidiClass(res);
-+    return res;
-+}
- 
- inline
--void Segment::finalise(const Font *font)
-+void Segment::finalise(const Font *font, bool reverse)
- {
-     if (!m_first) return;
- 
--    m_advance = positionSlots(font);
--    associateChars(0, m_numCharinfo);
-+    m_advance = positionSlots(font, m_first, m_last, m_silf->dir(), true);
-+    //associateChars(0, m_numCharinfo);
-+    if (reverse && currdir() != (m_dir & 1))
-+        reverseSlots();
-     linkClusters(m_first, m_last);
- }
- 
- inline
--int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel) const {
-+int32 Segment::getGlyphMetric(Slot *iSlot, uint8 metric, uint8 attrLevel, bool rtl) const {
-     if (attrLevel > 0)
-     {
-         Slot *is = findRoot(iSlot);
--        return is->clusterMetric(this, metric, attrLevel);
-+        return is->clusterMetric(this, metric, attrLevel, rtl);
-     }
-     else
-         return m_face->getGlyphMetric(iSlot->gid(), metric);
- }
- 
- inline
- bool Segment::isWhitespace(const int cid) const
- {
-@@ -206,68 +237,12 @@ bool Segment::isWhitespace(const int cid
-          + (cid >= 0x2000) * (cid <= 0x200A)
-          + (cid == 0x2028)
-          + (cid == 0x2029)
-          + (cid == 0x202F)
-          + (cid == 0x205F)
-          + (cid == 0x3000)) != 0;
- }
- 
--//inline
--//bool Segment::isWhitespace(const int cid) const
--//{
--//    switch (cid >> 8)
--//    {
--//        case 0x00:
--//            switch (cid)
--//            {
--//            case 0x09:
--//            case 0x0A:
--//            case 0x0B:
--//            case 0x0C:
--//            case 0x0D:
--//            case 0x20:
--//                return true;
--//            default:
--//                break;
--//            }
--//            break;
--//        case 0x16:
--//            return cid == 0x1680;
--//            break;
--//        case 0x18:
--//            return cid == 0x180E;
--//            break;
--//        case 0x20:
--//            switch (cid)
--//            {
--//            case 0x00:
--//            case 0x01:
--//            case 0x02:
--//            case 0x03:
--//            case 0x04:
--//            case 0x05:
--//            case 0x06:
--//            case 0x07:
--//            case 0x08:
--//            case 0x09:
--//            case 0x0A:
--//            case 0x28:
--//            case 0x29:
--//            case 0x2F:
--//            case 0x5F:
--//                return true
--//            default:
--//                break;
--//            }
--//            break;
--//        case 0x30:
--//            return cid == 0x3000;
--//            break;
--//    }
--//
--//    return false;
--//}
--
- } // namespace graphite2
- 
- struct gr_segment : public graphite2::Segment {};
- 
-diff --git a/gfx/graphite2/src/inc/Silf.h b/gfx/graphite2/src/inc/Silf.h
---- a/gfx/graphite2/src/inc/Silf.h
-+++ b/gfx/graphite2/src/inc/Silf.h
-@@ -80,24 +80,26 @@ public:
-     uint16 getClassGlyph(uint16 cid, unsigned int index) const;
-     uint16 findPseudo(uint32 uid) const;
-     uint8 numUser() const { return m_aUser; }
-     uint8 aPseudo() const { return m_aPseudo; }
-     uint8 aBreak() const { return m_aBreak; }
-     uint8 aMirror() const {return m_aMirror; }
-     uint8 aPassBits() const { return m_aPassBits; }
-     uint8 aBidi() const { return m_aBidi; }
-+    uint8 aCollision() const { return m_aCollision; }
-     uint8 substitutionPass() const { return m_sPass; }
-     uint8 positionPass() const { return m_pPass; }
-     uint8 justificationPass() const { return m_jPass; }
-     uint8 bidiPass() const { return m_bPass; }
-     uint8 numPasses() const { return m_numPasses; }
-     uint8 maxCompPerLig() const { return m_iMaxComp; }
-     uint16 numClasses() const { return m_nClass; }
-     byte  flags() const { return m_flags; }
-+    byte  dir() const { return m_dir; }
-     uint8 numJustLevels() const { return m_numJusts; }
-     Justinfo *justAttrs() const { return m_justs; }
-     uint16 endLineGlyphid() const { return m_gEndLine; }
-     const gr_faceinfo *silfInfo() const { return &m_silfinfo; }
- 
-     CLASS_NEW_DELETE;
- 
- private:
-@@ -107,23 +109,20 @@ private:
-     Pass          * m_passes;
-     Pseudo        * m_pseudos;
-     uint32        * m_classOffsets;
-     uint16        * m_classData;
-     Justinfo      * m_justs;
-     uint8           m_numPasses;
-     uint8           m_numJusts;
-     uint8           m_sPass, m_pPass, m_jPass, m_bPass,
--                    m_flags;
-+                    m_flags, m_dir;
- 
--    uint8   m_aPseudo, m_aBreak, m_aUser, m_aBidi, m_aMirror, m_aPassBits,
--            m_iMaxComp;
--    uint16  m_aLig,
--            m_numPseudo,
--            m_nClass,
--            m_nLinear,
--            m_gEndLine;
-+    uint8       m_aPseudo, m_aBreak, m_aUser, m_aBidi, m_aMirror, m_aPassBits,
-+                m_iMaxComp, m_aCollision;
-+    uint16      m_aLig, m_numPseudo, m_nClass, m_nLinear,
-+                m_gEndLine;
-     gr_faceinfo m_silfinfo;
-     
-     void releaseBuffers() throw();
- };
- 
- } // namespace graphite2
-diff --git a/gfx/graphite2/src/inc/Slot.h b/gfx/graphite2/src/inc/Slot.h
---- a/gfx/graphite2/src/inc/Slot.h
-+++ b/gfx/graphite2/src/inc/Slot.h
-@@ -27,25 +27,23 @@ of the License or (at your option) any l
- #pragma once
- 
- #include "graphite2/Types.h"
- #include "graphite2/Segment.h"
- #include "inc/Main.h"
- #include "inc/Font.h"
- #include "inc/Position.h"
- 
--
--
- namespace graphite2 {
- 
- typedef gr_attrCode attrCode;
- 
- class GlyphFace;
-+class SegCacheEntry;
- class Segment;
--class SegCacheEntry;
- 
- struct SlotJustify
- {
-     static const int NUMJUSTPARAMS = 5;
- 
-     SlotJustify(const SlotJustify &);
-     SlotJustify & operator = (const SlotJustify &);
- 
-@@ -70,73 +68,79 @@ class Slot
-     };
- 
- public:
-     struct iterator;
- 
-     unsigned short gid() const { return m_glyphid; }
-     Position origin() const { return m_position; }
-     float advance() const { return m_advance.x; }
-+    void advance(Position &val) { m_advance = val; }
-     Position advancePos() const { return m_advance; }
-     int before() const { return m_before; }
-     int after() const { return m_after; }
-     uint32 index() const { return m_index; }
-     void index(uint32 val) { m_index = val; }
- 
--    Slot();
-+    Slot(int16 *m_userAttr = NULL);
-     void set(const Slot & slot, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars);
-     Slot *next() const { return m_next; }
-     void next(Slot *s) { m_next = s; }
-     Slot *prev() const { return m_prev; }
-     void prev(Slot *s) { m_prev = s; }
-     uint16 glyph() const { return m_realglyphid ? m_realglyphid : m_glyphid; }
-     void setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph = NULL);
-     void setRealGid(uint16 realGid) { m_realglyphid = realGid; }
-     void adjKern(const Position &pos) { m_shift = m_shift + pos; m_advance = m_advance + pos; }
-     void origin(const Position &pos) { m_position = pos + m_shift; }
-     void originate(int ind) { m_original = ind; }
-     int original() const { return m_original; }
-     void before(int ind) { m_before = ind; }
-     void after(int ind) { m_after = ind; }
-     bool isBase() const { return (!m_parent); }
-     void update(int numSlots, int numCharInfo, Position &relpos);
--    Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin);
-+    Position finalise(const Segment* seg, const Font* font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin, bool rtl, bool isFinal);
-     bool isDeleted() const { return (m_flags & DELETED) ? true : false; }
-     void markDeleted(bool state) { if (state) m_flags |= DELETED; else m_flags &= ~DELETED; }
-     bool isCopied() const { return (m_flags & COPIED) ? true : false; }
-     void markCopied(bool state) { if (state) m_flags |= COPIED; else m_flags &= ~COPIED; }
-     bool isPositioned() const { return (m_flags & POSITIONED) ? true : false; }
-     void markPositioned(bool state) { if (state) m_flags |= POSITIONED; else m_flags &= ~POSITIONED; }
-     bool isInsertBefore() const { return !(m_flags & INSERTED); }
-     uint8 getBidiLevel() const { return m_bidiLevel; }
-     void setBidiLevel(uint8 level) { m_bidiLevel = level; }
-+    int8 getBidiClass(const Segment *seg);
-     int8 getBidiClass() const { return m_bidiCls; }
-     void setBidiClass(int8 cls) { m_bidiCls = cls; }
-     int16 *userAttrs() const { return m_userAttr; }
-     void userAttrs(int16 *p) { m_userAttr = p; }
-     void markInsertBefore(bool state) { if (!state) m_flags |= INSERTED; else m_flags &= ~INSERTED; }
-     void setAttr(Segment* seg, attrCode ind, uint8 subindex, int16 val, const SlotMap & map);
-     int getAttr(const Segment *seg, attrCode ind, uint8 subindex) const;
-     int getJustify(const Segment *seg, uint8 level, uint8 subindex) const;
-     void setJustify(Segment *seg, uint8 level, uint8 subindex, int16 value);
-     bool isLocalJustify() const { return m_justs != NULL; };
-     void attachTo(Slot *ap) { m_parent = ap; }
-     Slot *attachedTo() const { return m_parent; }
-     Position attachOffset() const { return m_attach - m_with; }
-     Slot* firstChild() const { return m_child; }
-+    void firstChild(Slot *ap) { m_child = ap; }
-     bool child(Slot *ap);
-     Slot* nextSibling() const { return m_sibling; }
-+    void nextSibling(Slot *ap) { m_sibling = ap; }
-     bool sibling(Slot *ap);
-     bool removeChild(Slot *ap);
-     bool removeSibling(Slot *ap);
--    int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel);
-+    int32 clusterMetric(const Segment* seg, uint8 metric, uint8 attrLevel, bool rtl);
-     void positionShift(Position a) { m_position += a; }
-     void floodShift(Position adj);
-     float just() const { return m_just; }
-     void just(float j) { m_just = j; }
-+    Slot *nextInCluster(const Slot *s) const;
-+    bool isChildOf(const Slot *base) const;
- 
-     CLASS_NEW_DELETE
- 
- private:
-     Slot *m_next;           // linked list of slots
-     Slot *m_prev;
-     unsigned short m_glyphid;        // glyph id
-     uint16 m_realglyphid;
-diff --git a/gfx/graphite2/src/inc/Sparse.h b/gfx/graphite2/src/inc/Sparse.h
---- a/gfx/graphite2/src/inc/Sparse.h
-+++ b/gfx/graphite2/src/inc/Sparse.h
-@@ -51,17 +51,17 @@ private:
-     static const unsigned char  SIZEOF_CHUNK = (sizeof(mask_t) - sizeof(key_type))*8;
- 
-     struct chunk
-     {
-         mask_t          mask:SIZEOF_CHUNK;
-         key_type        offset;
-     };
- 
--    static chunk  empty_chunk;
-+    static const chunk  empty_chunk;
-     sparse(const sparse &);
-     sparse & operator = (const sparse &);
- 
- public:
-     template<typename I>
-     sparse(I first, const I last);
-     sparse() throw();
-     ~sparse() throw();
-@@ -83,17 +83,17 @@ private:
-     }           m_array;
-     key_type    m_nchunks;
- };
- 
- 
- inline
- sparse::sparse() throw() : m_nchunks(0)
- {
--    m_array.map = &empty_chunk;
-+    m_array.map = const_cast<graphite2::sparse::chunk *>(&empty_chunk);
- }
- 
- 
- template <typename I>
- sparse::sparse(I attr, const I last)
- : m_nchunks(0)
- {
-     m_array.map = 0;
-@@ -108,30 +108,31 @@ sparse::sparse(I attr, const I last)
-         if (v.first <= lastkey) { m_nchunks = 0; return; }
- 
-         lastkey = v.first;
-         const key_type k = v.first / SIZEOF_CHUNK;
-         if (k >= m_nchunks) m_nchunks = k+1;
-     }
-     if (m_nchunks == 0)
-     {
--        m_array.map=&empty_chunk;
-+        m_array.map=const_cast<graphite2::sparse::chunk *>(&empty_chunk);
-         return;
-     }
- 
-     m_array.values = grzeroalloc<mapped_type>((m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)
-                                                  / sizeof(mapped_type)
-                                                  + n_values);
- 
-     if (m_array.values == 0)
-     {
-         free(m_array.values); m_array.map=0;
-         return;
-     }
- 
-+    // coverity[forward_null : FALSE] Since m_array is union and m_array.values is not NULL
-     chunk * ci = m_array.map;
-     ci->offset = (m_nchunks*sizeof(chunk) + sizeof(mapped_type)-1)/sizeof(mapped_type);
-     mapped_type * vi = m_array.values + ci->offset;
-     for (; attr != last; ++attr, ++vi)
-     {
-         const typename std::iterator_traits<I>::value_type v = *attr;
-         if (v.second == 0)  { --vi; continue; }
- 
-diff --git a/gfx/graphite2/src/inc/TtfUtil.h b/gfx/graphite2/src/inc/TtfUtil.h
---- a/gfx/graphite2/src/inc/TtfUtil.h
-+++ b/gfx/graphite2/src/inc/TtfUtil.h
-@@ -132,21 +132,21 @@ public:
-     int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId,
-         int *nameIdList, int cNameIds, short *langIdList);
-     void SwapWString(void * pWStr, size_t nSize = 0); // throw (std::invalid_argument);
- #endif
- 
-     ////////////////////////////////// cmap lookup tools 
-     const void * FindCmapSubtable(const void * pCmap, int nPlatformId = 3, 
-         int nEncodingId = 1, size_t length = 0);
--    bool CheckCmapSubtable4(const void * pCmap31);
-+    bool CheckCmapSubtable4(const void * pCmap31, size_t table_len /*, unsigned int maxgid*/);
-     gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey = 0);
-     unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId,
-         int * pRangeKey = 0);
--    bool CheckCmapSubtable12(const void *pCmap310);
-+    bool CheckCmapSubtable12(const void *pCmap310, size_t table_len /*, unsigned int maxgid*/);
-     gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey = 0);
-     unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId,
-         int * pRangeKey = 0);
- 
-     ///////////////////////////////// horizontal metric data for a glyph
-     bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, 
-         const void * pHhea, int & nLsb, unsigned int & nAdvWid);
- 
-diff --git a/gfx/graphite2/src/inc/UtfCodec.h b/gfx/graphite2/src/inc/UtfCodec.h
---- a/gfx/graphite2/src/inc/UtfCodec.h
-+++ b/gfx/graphite2/src/inc/UtfCodec.h
-@@ -126,19 +126,22 @@ public:
-     static uchar_t get(const codeunit_t * cp, int8 & l) throw()
-     {
-         const int8 seq_sz = sz_lut[*cp >> 4];
-         uchar_t u = *cp & mask_lut[seq_sz];
-         l = 1;
-         bool toolong = false;
- 
-         switch(seq_sz) {
--            case 4:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong  = (u < 0x10); // no break
--            case 3:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x20); // no break
--            case 2:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x80); // no break
-+            case 4:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong  = (u < 0x10); GR_FALLTHROUGH;
-+                // no break
-+            case 3:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x20); GR_FALLTHROUGH;
-+                // no break
-+            case 2:     u <<= 6; u |= *++cp & 0x3F; if (*cp >> 6 != 2) break; ++l; toolong |= (u < 0x80); GR_FALLTHROUGH;
-+                // no break
-             case 1:     break;
-             case 0:     l = -1; return 0xFFFD;
-         }
- 
-         if (l != seq_sz || toolong)
-         {
-             l = -l;
-             return 0xFFFD;
-diff --git a/gfx/graphite2/src/inc/bits.h b/gfx/graphite2/src/inc/bits.h
---- a/gfx/graphite2/src/inc/bits.h
-+++ b/gfx/graphite2/src/inc/bits.h
-@@ -24,25 +24,73 @@ Mozilla Public License (http://mozilla.o
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
- #pragma once
- 
- namespace graphite2
- {
- 
-+
-+#if defined GRAPHITE2_BUILTINS && (defined __GNUC__ || defined __clang__)
-+
- template<typename T>
- inline unsigned int bit_set_count(T v)
- {
--    v = v - ((v >> 1) & T(~T(0)/3));                           // temp
--    v = (v & T(~T(0)/15*3)) + ((v >> 2) & T(~T(0)/15*3));      // temp
--    v = (v + (v >> 4)) & T(~T(0)/255*15);                      // temp
--    return (T)(v * T(~T(0)/255)) >> (sizeof(T)-1)*8;           // count
-+    return __builtin_popcount(v);
- }
- 
-+template<>
-+inline unsigned int bit_set_count(int16 v)
-+{
-+    return __builtin_popcount(static_cast<uint16>(v));
-+}
-+
-+template<>
-+inline unsigned int bit_set_count(int8 v)
-+{
-+    return __builtin_popcount(static_cast<uint8>(v));
-+}
-+
-+template<>
-+inline unsigned int bit_set_count(unsigned long v)
-+{
-+    return __builtin_popcountl(v);
-+}
-+
-+template<>
-+inline unsigned int bit_set_count(signed long v)
-+{
-+    return __builtin_popcountl(v);
-+}
-+
-+template<>
-+inline unsigned int bit_set_count(unsigned long long v)
-+{
-+    return __builtin_popcountll(v);
-+}
-+
-+template<>
-+inline unsigned int bit_set_count(signed long long v)
-+{
-+    return __builtin_popcountll(v);
-+}
-+#else
-+
-+template<typename T>
-+inline unsigned int bit_set_count(T v)
-+{
-+    v = v - ((v >> 1) & T(~(0UL)/3));                           // temp
-+    v = (v & T(~(0UL)/15*3)) + ((v >> 2) & T(~(0UL)/15*3));     // temp
-+    v = (v + (v >> 4)) & T(~(0UL)/255*15);                      // temp
-+    return (T)(v * T(~(0UL)/255)) >> (sizeof(T)-1)*8;           // count
-+}
-+
-+#endif
-+
- 
- template<int S>
- inline unsigned long _mask_over_val(unsigned long v)
- {
-     v = _mask_over_val<S/2>(v);
-     v |= v >> S*4;
-     return v;
- }
-@@ -82,9 +130,17 @@ inline T has_zero(const T x)
- 
- template<typename T>
- inline T zero_bytes(const T x, unsigned char n)
- {
-     const T t = T(~T(0)/255*n);
-     return T((has_zero(x^t) >> 7)*n);
- }
- 
-+#if 0
-+inline float float_round(float x, uint32 m)
-+{
-+    *reinterpret_cast<unsigned int *>(&x) &= m;
-+    return *reinterpret_cast<float *>(&x);
- }
-+#endif
-+
-+}
-diff --git a/gfx/graphite2/src/inc/debug.h b/gfx/graphite2/src/inc/debug.h
---- a/gfx/graphite2/src/inc/debug.h
-+++ b/gfx/graphite2/src/inc/debug.h
-@@ -49,31 +49,39 @@ struct objectid
- {
-     char name[16];
-     objectid(const dslot &) throw();
-     objectid(const Segment * const p) throw();
- };
- 
- 
- json & operator << (json & j, const Position &) throw();
-+json & operator << (json & j, const Rect &) throw();
- json & operator << (json & j, const CharInfo &) throw();
- json & operator << (json & j, const dslot &) throw();
- json & operator << (json & j, const objectid &) throw();
- json & operator << (json & j, const telemetry &) throw();
- 
- 
- 
- inline
- json & operator << (json & j, const Position & p) throw()
- {
-     return j << json::flat << json::array << p.x << p.y << json::close;
- }
- 
- 
- inline
-+json & operator << (json & j, const Rect & p) throw()
-+{
-+    return j << json::flat << json::array << p.bl.x << p.bl.y << p.tr.x << p.tr.y << json::close;
-+}
-+
-+
-+inline
- json & operator << (json & j, const objectid & sid) throw()
- {
-     return j << sid.name;
- }
- 
- 
- } // namespace graphite2
- 
-diff --git a/gfx/graphite2/src/inc/json.h b/gfx/graphite2/src/inc/json.h
---- a/gfx/graphite2/src/inc/json.h
-+++ b/gfx/graphite2/src/inc/json.h
-@@ -24,19 +24,21 @@ Mozilla Public License (http://mozilla.o
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
- // JSON pretty printer for graphite font debug output logging.
- // Created on: 15 Dec 2011
- //     Author: Tim Eves
- 
- #pragma once
-+
- #include "inc/Main.h"
- #include <cassert>
--#include <stdio.h>
-+#include <cstdio>
-+#include "inc/List.h"
- 
- namespace graphite2 {
- 
- class json
- {
-     // Prevent copying
-     json(const json &);
-     json & operator = (const json &);
-@@ -44,31 +46,36 @@ class json
-     typedef void (*_context_t)(json &);
-     class _null_t {};
- 
-     FILE * const    _stream;
-     char            _contexts[128], // context stack
-                   * _context,       // current context (top of stack)
-                   * _flatten;       // if !0 points to context above which
-                                     //  pretty printed output should occur.
-+    Vector<void *>  _env;
- 
-     void context(const char current) throw();
-     void indent(const int d=0) throw();
-     void push_context(const char, const char) throw();
-     void pop_context() throw();
- 
- public:
-     class closer;
- 
-     typedef const char *    string;
-     typedef double          number;
-     typedef long signed int integer;
-     typedef bool            boolean;
-     static const _null_t    null;
- 
-+    void setenv(unsigned int index, void *val) { _env.reserve(index + 1); if (index >= _env.size()) _env.insert(_env.end(), _env.size() - index + 1, 0); _env[index] = val; }
-+    void *getenv(unsigned int index) const { return _env[index]; }
-+    const Vector<void *> &getenvs() const { return _env; }
-+
-     static void flat(json &) throw();
-     static void close(json &) throw();
-     static void object(json &) throw();
-     static void array(json &) throw();
-     static void item(json &) throw();
- 
-     json(FILE * stream) throw();
-     ~json() throw ();
-diff --git a/gfx/graphite2/src/inc/opcode_table.h b/gfx/graphite2/src/inc/opcode_table.h
---- a/gfx/graphite2/src/inc/opcode_table.h
-+++ b/gfx/graphite2/src/inc/opcode_table.h
-@@ -38,17 +38,17 @@ of the License or (at your option) any l
- //      sattrnum - 0 .. 29 (gr_slatJWidth) , 55 (gr_slatUserDefn)
- //      attrid - 0 .. silf.numUser() where sattrnum == 55; 0..silf.m_iMaxComp where sattrnum == 15 otherwise 0
- //      gattrnum - 0 .. face->getGlyphFaceCache->numAttrs()
- //      gmetric - 0 .. 11 (kgmetDescent)
- //      featidx - 0 .. face.numFeatures()
- //      level - any byte
- static const opcode_t opcode_table[] = 
- {
--    {{do2(nop)},                                    0,  "NOP"},
-+    {{do2(nop)},                                    0, "NOP"},
- 
-     {{do2(push_byte)},                              1, "PUSH_BYTE"},                // number
-     {{do2(push_byte_u)},                            1, "PUSH_BYTE_U"},              // number
-     {{do2(push_short)},                             2, "PUSH_SHORT"},               // number number
-     {{do2(push_short_u)},                           2, "PUSH_SHORT_U"},             // number number
-     {{do2(push_long)},                              4, "PUSH_LONG"},                // number number number number
- 
-     {{do2(add)},                                    0, "ADD"},
-@@ -109,12 +109,17 @@ static const opcode_t opcode_table[] =
-     {{do2(push_proc_state)},                        1, "PUSH_PROC_STATE"},          // dummy
-     {{do2(push_version)},                           0, "PUSH_VERSION"},
-     {{do_(put_subs), NILOP},                        5, "PUT_SUBS"},                 // slot input_class input_class output_class output_class
-     {{NILOP,NILOP},                                 0, "PUT_SUBS2"},
-     {{NILOP,NILOP},                                 0, "PUT_SUBS3"},
-     {{do_(put_glyph), NILOP},                       2, "PUT_GLYPH"},                // output_class output_class
-     {{do2(push_glyph_attr)},                        3, "PUSH_GLYPH_ATTR"},          // gattrnum gattrnum slot
-     {{do2(push_att_to_glyph_attr)},                 3, "PUSH_ATT_TO_GLYPH_ATTR"},   // gattrnum gattrnum slot
-+    {{do2(bor)},                                    0, "BITOR"},
-+    {{do2(band)},                                   0, "BITAND"},
-+    {{do2(bnot)},                                   0, "BITNOT"},   // 0x40
-+    {{do2(setbits)},                                4, "BITSET"},
-+    {{do2(set_feat)},                               2, "SET_FEAT"},
-     // private opcodes for internal use only, comes after all other on disk opcodes.
-     {{do_(temp_copy), NILOP},                       0, "TEMP_COPY"}
- };
- 
-diff --git a/gfx/graphite2/src/inc/opcodes.h b/gfx/graphite2/src/inc/opcodes.h
---- a/gfx/graphite2/src/inc/opcodes.h
-+++ b/gfx/graphite2/src/inc/opcodes.h
-@@ -56,16 +56,17 @@ of the License or (at your option) any l
- //                    pushed.
- //        seg       = A reference to the Segment this code is running over.
- //        is        = The current slot index
- //        isb       = The original base slot index at the start of this rule
- //        isf       = The first positioned slot
- //        isl       = The last positioned slot
- //        ip        = The current instruction pointer
- //        endPos    = Position of advance of last cluster
-+//        dir       = writing system directionality of the font
-      
- 
- // #define NOT_IMPLEMENTED     assert(false)
- #define NOT_IMPLEMENTED
- 
- #define binop(op)           const int32 a = pop(); *sp = int32(*sp) op a
- #define use_params(n)       dp += n
- 
-@@ -236,30 +237,34 @@ STARTOP(put_subs_8bit_obs)
-         index = seg.findClassIndex(input_class, slot->gid());
-         is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
-     }
- ENDOP
- 
- STARTOP(put_copy)
-     declare_params(1);
-     const int  slot_ref = int8(*param);
--    if (is && (slot_ref ||is != *map))
-+    if (is)
-     {
--        int16 *tempUserAttrs = is->userAttrs();
-         slotref ref = slotat(slot_ref);
--        if (ref)
-+        if (ref && ref != is)
-         {
--            memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
-+            int16 *tempUserAttrs = is->userAttrs();
-+            if (is->attachedTo() || is->firstChild()) DIE
-             Slot *prev = is->prev();
-             Slot *next = is->next();
--            memcpy(is, slotat(slot_ref), sizeof(Slot));
-+            memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
-+            memcpy(is, ref, sizeof(Slot));
-+            is->firstChild(NULL);
-+            is->nextSibling(NULL);
-             is->userAttrs(tempUserAttrs);
-             is->next(next);
-             is->prev(prev);
--            is->sibling(NULL);
-+            if (is->attachedTo())
-+                is->attachedTo()->child(is);
-         }
-         is->markCopied(false);
-         is->markDeleted(false);
-     }
- ENDOP
- 
- STARTOP(insert)
-     Slot *newSlot = seg.newSlot();
-@@ -304,24 +309,26 @@ STARTOP(insert)
-     {
-         newSlot->originate(newSlot->prev()->original());
-         newSlot->after(newSlot->prev()->after());
-     }
-     else
-     {
-         newSlot->originate(seg.defaultOriginal());
-     }
-+    if (is == smap.highwater())
-+        smap.highpassed(false);
-     is = newSlot;
-     seg.extendLength(1);
-     if (map != &smap[-1]) 
-         --map;
- ENDOP
- 
- STARTOP(delete_)
--    if (!is) DIE
-+    if (!is || is->isDeleted()) DIE
-     is->markDeleted(true);
-     if (is->prev())
-         is->prev()->next(is->next());
-     else
-         seg.first(is->next());
-     
-     if (is->next())
-         is->next()->prev(is->prev());
-@@ -380,30 +387,30 @@ STARTOP(attr_set)
- ENDOP
- 
- STARTOP(attr_add)
-     declare_params(1);
-     const attrCode      slat = attrCode(uint8(*param));
-     const          int  val  = int(pop());
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-         flags |= POSITIONED;
-     }
-     int res = is->getAttr(&seg, slat, 0);
-     is->setAttr(&seg, slat, 0, val + res, smap);
- ENDOP
- 
- STARTOP(attr_sub)
-     declare_params(1);
-     const attrCode      slat = attrCode(uint8(*param));
-     const          int  val  = int(pop());
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-         flags |= POSITIONED;
-     }
-     int res = is->getAttr(&seg, slat, 0);
-     is->setAttr(&seg, slat, 0, res - val, smap);
- ENDOP
- 
- STARTOP(attr_set_slot)
-     declare_params(1);
-@@ -422,17 +429,17 @@ STARTOP(iattr_set_slot)
- ENDOP
- 
- STARTOP(push_slot_attr)
-     declare_params(2);
-     const attrCode      slat     = attrCode(uint8(param[0]));
-     const int           slot_ref = int8(param[1]);
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-         flags |= POSITIONED;
-     }
-     slotref slot = slotat(slot_ref);
-     if (slot)
-     {
-         int res = slot->getAttr(&seg, slat, 0);
-         push(res);
-     }
-@@ -449,17 +456,17 @@ ENDOP
- 
- STARTOP(push_glyph_metric)
-     declare_params(3);
-     const unsigned int  glyph_attr  = uint8(param[0]);
-     const int           slot_ref    = int8(param[1]);
-     const signed int    attr_level  = uint8(param[2]);
-     slotref slot = slotat(slot_ref);
-     if (slot)
--        push(seg.getGlyphMetric(slot, glyph_attr, attr_level));
-+        push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));
- ENDOP
- 
- STARTOP(push_feat)
-     declare_params(2);
-     const unsigned int  feat        = uint8(param[0]);
-     const int           slot_ref    = int8(param[1]);
-     slotref slot = slotat(slot_ref);
-     if (slot)
-@@ -487,28 +494,28 @@ STARTOP(push_att_to_glyph_metric)
-     const unsigned int  glyph_attr  = uint8(param[0]);
-     const int           slot_ref    = int8(param[1]);
-     const signed int    attr_level  = uint8(param[2]);
-     slotref slot = slotat(slot_ref);
-     if (slot)
-     {
-         slotref att = slot->attachedTo();
-         if (att) slot = att;
--        push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level)));
-+        push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));
-     }
- ENDOP
- 
- STARTOP(push_islot_attr)
-     declare_params(3);
-     const attrCode  slat     = attrCode(uint8(param[0]));
-     const int           slot_ref = int8(param[1]),
-                         idx      = uint8(param[2]);
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-         flags |= POSITIONED;
-     }
-     slotref slot = slotat(slot_ref);
-     if (slot)
-     {
-         int res = slot->getAttr(&seg, slat, idx);
-         push(res);
-     }
-@@ -543,31 +550,31 @@ ENDOP
- 
- STARTOP(iattr_add)
-     declare_params(2);
-     const attrCode      slat = attrCode(uint8(param[0]));
-     const size_t        idx  = uint8(param[1]);
-     const          int  val  = int(pop());
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-         flags |= POSITIONED;
-     }
-     int res = is->getAttr(&seg, slat, idx);
-     is->setAttr(&seg, slat, idx, val + res, smap);
- ENDOP
- 
- STARTOP(iattr_sub)
-     declare_params(2);
-     const attrCode      slat = attrCode(uint8(param[0]));
-     const size_t        idx  = uint8(param[1]);
-     const          int  val  = int(pop());
-     if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
-     {
--        seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
-+        seg.positionSlots(0, *smap.begin(), *(smap.end()-1), dir);
-         flags |= POSITIONED;
-     }
-     int res = is->getAttr(&seg, slat, idx);
-     is->setAttr(&seg, slat, idx, res - val, smap);
- ENDOP
- 
- STARTOP(push_proc_state)
-     use_params(1);
-@@ -631,16 +638,50 @@ STARTOP(push_att_to_glyph_attr)
-         slotref att = slot->attachedTo();
-         if (att) slot = att;
-         push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
-     }
- ENDOP
- 
- STARTOP(temp_copy)
-     slotref newSlot = seg.newSlot();
--    if (!newSlot) DIE;
-+    if (!newSlot || !is) DIE;
-     int16 *tempUserAttrs = newSlot->userAttrs();
-     memcpy(newSlot, is, sizeof(Slot));
-     memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
-     newSlot->userAttrs(tempUserAttrs);
-     newSlot->markCopied(true);
-     *map = newSlot;
- ENDOP
-+
-+STARTOP(band)
-+    binop(&);
-+ENDOP
-+
-+STARTOP(bor)
-+    binop(|);
-+ENDOP
-+
-+STARTOP(bnot)
-+    *sp = ~*sp;
-+ENDOP
-+
-+STARTOP(setbits)
-+    declare_params(4);
-+    const uint16 m  = uint16(param[0]) << 8
-+                    | uint8(param[1]);
-+    const uint16 v  = uint16(param[2]) << 8
-+                    | uint8(param[3]);
-+    *sp = ((*sp) & ~m) | v;
-+ENDOP
-+
-+STARTOP(set_feat)
-+    declare_params(2);
-+    const unsigned int  feat        = uint8(param[0]);
-+    const int           slot_ref    = int8(param[1]);
-+    slotref slot = slotat(slot_ref);
-+    if (slot)
-+    {
-+        uint8 fid = seg.charinfo(slot->original())->fid();
-+        seg.setFeature(fid, feat, pop());
-+    }
-+ENDOP
-+
-diff --git a/gfx/graphite2/src/json.cpp b/gfx/graphite2/src/json.cpp
---- a/gfx/graphite2/src/json.cpp
-+++ b/gfx/graphite2/src/json.cpp
-@@ -24,17 +24,18 @@ Mozilla Public License (http://mozilla.o
- License, as published by the Free Software Foundation, either version 2
- of the License or (at your option) any later version.
- */
- // JSON debug logging
- // Author: Tim Eves
- 
- #if !defined GRAPHITE2_NTRACING
- 
--#include <stdio.h>
-+#include <cstdio>
-+#include <limits>
- #include "inc/json.h"
- 
- using namespace graphite2;
- 
- namespace
- {
-     enum
-     {
-@@ -111,16 +112,29 @@ json & json::operator << (json::string s
-     const char ctxt = _context[-1] == obj ? *_context == member ? seq : member : seq;
-     context(ctxt);
-     fprintf(_stream, "\"%s\"", s);
-     if (ctxt == member) fputc(' ', _stream);
- 
-     return *this;
- }
- 
--json & json::operator << (json::number f) throw()   { context(seq); fprintf(_stream, "%g", f); return *this; }
-+json & json::operator << (json::number f) throw()
-+{ 
-+    context(seq); 
-+    if (std::numeric_limits<json::number>::infinity() == f)
-+        fputs("Infinity", _stream);
-+    else if (-std::numeric_limits<json::number>::infinity() == f)
-+        fputs("-Infinity", _stream);
-+    else if (std::numeric_limits<json::number>::quiet_NaN() == f ||
-+            std::numeric_limits<json::number>::signaling_NaN() == f)
-+        fputs("NaN", _stream);
-+    else
-+        fprintf(_stream, "%g", f); 
-+    return *this; 
-+}
- json & json::operator << (json::integer d) throw()  { context(seq); fprintf(_stream, "%ld", d); return *this; }
- json & json::operator << (long unsigned d) throw()  { context(seq); fprintf(_stream, "%ld", d); return *this; }
- json & json::operator << (json::boolean b) throw()  { context(seq); fputs(b ? "true" : "false", _stream); return *this; }
- json & json::operator << (json::_null_t) throw()    { context(seq); fputs("null",_stream); return *this; }
- 
- #endif
- 
-diff --git a/gfx/graphite2/src/moz.build b/gfx/graphite2/src/moz.build
---- a/gfx/graphite2/src/moz.build
-+++ b/gfx/graphite2/src/moz.build
-@@ -18,37 +18,40 @@ if CONFIG['GNU_CC']:
-     ]
- else:
-     UNIFIED_SOURCES += [
-         'call_machine.cpp'
-     ]
- 
- # This should contain all of the _SOURCES from files.mk, except *_machine.cpp
- UNIFIED_SOURCES += [
--    'Bidi.cpp',
-     'CachedFace.cpp',
-     'CmapCache.cpp',
-     'Code.cpp',
-+    'Collider.cpp',
-+    'Decompressor.cpp',
-     'Face.cpp',
-     'FeatureMap.cpp',
-     'FileFace.cpp',
-     'Font.cpp',
-     'GlyphCache.cpp',
-     'GlyphFace.cpp',
-     'gr_char_info.cpp',
-     'gr_face.cpp',
-     'gr_features.cpp',
-     'gr_font.cpp',
-     'gr_logging.cpp',
-     'gr_segment.cpp',
-     'gr_slot.cpp',
-+    'Intervals.cpp',
-     'json.cpp',
-     'Justifier.cpp',
-     'NameTable.cpp',
-     'Pass.cpp',
-+    'Position.cpp',
-     'SegCache.cpp',
-     'SegCacheEntry.cpp',
-     'SegCacheStore.cpp',
-     'Segment.cpp',
-     'Silf.cpp',
-     'Slot.cpp',
-     'Sparse.cpp',
-     'TtfUtil.cpp',
-
diff --git a/gnu/packages/patches/imlib2-CVE-2016-4024.patch b/gnu/packages/patches/imlib2-CVE-2016-4024.patch
new file mode 100644
index 0000000000..c4f1f21b28
--- /dev/null
+++ b/gnu/packages/patches/imlib2-CVE-2016-4024.patch
@@ -0,0 +1,52 @@
+Fix CVE-2016-4024 (integer overflow in lib/image.h).
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-4024
+
+Upstream source:
+https://git.enlightenment.org/legacy/imlib2.git/commit/?id=7eba2e4c8ac0e20838947f10f29d0efe1add8227
+
+From 7eba2e4c8ac0e20838947f10f29d0efe1add8227 Mon Sep 17 00:00:00 2001
+From: "Yuriy M. Kaminskiy" <yumkam@gmail.com>
+Date: Wed, 6 Apr 2016 03:34:01 +0300
+Subject: Fix integer overflow resulting in insufficient heap allocation
+
+IMAGE_DIMENSIONS_OK ensures that image width and height are less then
+46340, so that maximum number of pixels is ~2**31.
+
+Unfortunately, there are a lot of code that allocates image data with
+something like
+
+   malloc(w * h * sizeof(DATA32));
+
+Obviously, on 32-bit machines this results in integer overflow,
+insufficient heap allocation, with [massive] out-of-bounds heap
+overwrite.
+Either X_MAX should be reduced to 32767, or (w)*(h) should be checked to
+not exceed ULONG_MAX/sizeof(DATA32).
+
+Security implications:
+*) for 32-bit machines: insufficient heap allocation and heap overwrite
+in many image loaders, with escalation potential to remote code
+execution;
+*) for 64-bit machines: it seems, no impact.
+---
+ src/lib/image.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/lib/image.h b/src/lib/image.h
+index e9eb678..5fae6ed 100644
+--- a/src/lib/image.h
++++ b/src/lib/image.h
+@@ -188,7 +188,8 @@ void                __imlib_SaveImage(ImlibImage * im, const char *file,
+ 
+ /* The maximum pixmap dimension is 65535. */
+ /* However, for now, use 46340 (46340^2 < 2^31) to avoid buffer overflow issues. */
+-#define X_MAX_DIM 46340
++/* Reduced further to 32767, so that (w * h * sizeof(DATA32)) won't exceed ULONG_MAX */
++#define X_MAX_DIM 32767
+ 
+ #define IMAGE_DIMENSIONS_OK(w, h) \
+    ( ((w) > 0) && ((h) > 0) && ((w) < X_MAX_DIM) && ((h) < X_MAX_DIM) )
+-- 
+cgit v0.12
+
diff --git a/gnu/packages/patches/openssh-CVE-2015-8325.patch b/gnu/packages/patches/openssh-CVE-2015-8325.patch
new file mode 100644
index 0000000000..8063e64ea7
--- /dev/null
+++ b/gnu/packages/patches/openssh-CVE-2015-8325.patch
@@ -0,0 +1,31 @@
+From 85bdcd7c92fe7ff133bbc4e10a65c91810f88755 Mon Sep 17 00:00:00 2001
+From: Damien Miller <djm@mindrot.org>
+Date: Wed, 13 Apr 2016 10:39:57 +1000
+Subject: ignore PAM environment vars when UseLogin=yes
+
+If PAM is configured to read user-specified environment variables
+and UseLogin=yes in sshd_config, then a hostile local user may
+attack /bin/login via LD_PRELOAD or similar environment variables
+set via PAM.
+
+CVE-2015-8325, found by Shayan Sadigh, via Colin Watson
+---
+ session.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/session.c b/session.c
+index 4859245..4653b09 100644
+--- a/session.c
++++ b/session.c
+@@ -1322,7 +1322,7 @@ do_setup_env(Session *s, const char *shell)
+ 	 * Pull in any environment variables that may have
+ 	 * been set by PAM.
+ 	 */
+-	if (options.use_pam) {
++	if (options.use_pam && !options.use_login) {
+ 		char **p;
+ 
+ 		p = fetch_pam_child_environment();
+-- 
+cgit v0.11.2
+
diff --git a/gnu/packages/patches/poppler-CVE-2015-8868.patch b/gnu/packages/patches/poppler-CVE-2015-8868.patch
new file mode 100644
index 0000000000..ac78d32ffa
--- /dev/null
+++ b/gnu/packages/patches/poppler-CVE-2015-8868.patch
@@ -0,0 +1,30 @@
+Fixes CVE-2015-8868 (heap overflow).
+
+Upstream source:
+https://cgit.freedesktop.org/poppler/poppler/commit/?id=b3425dd3261679958cd56c0f71995c15d2124433
+
+From b3425dd3261679958cd56c0f71995c15d2124433 Mon Sep 17 00:00:00 2001
+From: Albert Astals Cid <aacid@kde.org>
+Date: Tue, 22 Dec 2015 22:50:33 +0100
+Subject: Do not crash on invalid files
+
+Bug #93476
+
+diff --git a/poppler/Function.cc b/poppler/Function.cc
+index 67283df..ee5afc1 100644
+--- a/poppler/Function.cc
++++ b/poppler/Function.cc
+@@ -577,6 +577,10 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
+       goto err2;
+     }
+     n = obj1.arrayGetLength();
++    if (unlikely(n > funcMaxOutputs)) {
++      error(errSyntaxError, -1, "Function's C0 array is wrong length");
++      n = funcMaxOutputs;
++    }
+     for (i = 0; i < n; ++i) {
+       obj1.arrayGet(i, &obj2);
+       if (!obj2.isNum()) {
+-- 
+cgit v0.10.2
+
diff --git a/gnu/packages/patches/python-pandas-fix-tslib-test-failure.patch b/gnu/packages/patches/python-pandas-fix-tslib-test-failure.patch
new file mode 100644
index 0000000000..62d6a38086
--- /dev/null
+++ b/gnu/packages/patches/python-pandas-fix-tslib-test-failure.patch
@@ -0,0 +1,141 @@
+This patch is required to fix a test failure when python-dateutil version
+2.5.2 or later is used.  It is derived from the following commits:
+
+80ef4e06526b9b60cf24268454c9456585a790a3
+845ff974af6f7c3b3067cce8a7149b771c2be87
+
+diff --git a/pandas/tseries/tests/test_tslib.py b/pandas/tseries/tests/test_tslib.py
+index f0d5bf7..863bc6f 100644
+--- a/pandas/tseries/tests/test_tslib.py
++++ b/pandas/tseries/tests/test_tslib.py
+@@ -474,6 +474,11 @@ def test_does_not_convert_mixed_integer(self):
+                 good_date_string))
+ 
+     def test_parsers(self):
++
++        # https://github.com/dateutil/dateutil/issues/217
++        import dateutil
++        yearfirst = dateutil.__version__ >= LooseVersion('2.5.0')
++
+         cases = {'2011-01-01': datetime.datetime(2011, 1, 1),
+                  '2Q2005': datetime.datetime(2005, 4, 1),
+                  '2Q05': datetime.datetime(2005, 4, 1),
+@@ -527,20 +532,26 @@ def test_parsers(self):
+                  }
+ 
+         for date_str, expected in compat.iteritems(cases):
+-            result1, _, _ = tools.parse_time_string(date_str)
+-            result2 = to_datetime(date_str)
+-            result3 = to_datetime([date_str])
+-            result4 = to_datetime(np.array([date_str], dtype=object))
+-            result5 = Timestamp(date_str)
+-            result6 = DatetimeIndex([date_str])[0]
+-            result7 = date_range(date_str, freq='S', periods=1)
++            result1, _, _ = tools.parse_time_string(date_str,
++                                                    yearfirst=yearfirst)
++            result2 = to_datetime(date_str, yearfirst=yearfirst)
++            result3 = to_datetime([date_str], yearfirst=yearfirst)
++            result4 = to_datetime(np.array([date_str], dtype=object),
++                                  yearfirst=yearfirst)
++            result6 = DatetimeIndex([date_str], yearfirst=yearfirst)[0]
+             self.assertEqual(result1, expected)
+             self.assertEqual(result2, expected)
+             self.assertEqual(result3, expected)
+             self.assertEqual(result4, expected)
+-            self.assertEqual(result5, expected)
+             self.assertEqual(result6, expected)
+-            self.assertEqual(result7, expected)
++
++            # these really need to have yearfist, but we don't support
++            if not yearfirst:
++                result5 = Timestamp(date_str)
++                self.assertEqual(result5, expected)
++                result7 = date_range(date_str, freq='S', periods=1,
++                                     yearfirst=yearfirst)
++                self.assertEqual(result7, expected)
+ 
+         # NaT
+         result1, _, _ = tools.parse_time_string('NaT')
+@@ -589,23 +589,62 @@ def test_parsers_quarter_invalid(self):
+             self.assertRaises(ValueError, tools.parse_time_string, case)
+ 
+     def test_parsers_dayfirst_yearfirst(self):
++
++        # https://github.com/dateutil/dateutil/issues/217
++        # this issue was closed
++        import dateutil
++        is_compat_version = dateutil.__version__ >= LooseVersion('2.5.2')
++        if is_compat_version:
++            dayfirst_yearfirst1 = datetime.datetime(2010, 12, 11)
++            dayfirst_yearfirst2 = datetime.datetime(2020, 12, 21)
++        else:
++            dayfirst_yearfirst1 = datetime.datetime(2010, 11, 12)
++            dayfirst_yearfirst2 = datetime.datetime(2020, 12, 21)
++
+         # str : dayfirst, yearfirst, expected
+-        cases = {'10-11-12': [(False, False, datetime.datetime(2012, 10, 11)),
+-                              (True, False, datetime.datetime(2012, 11, 10)),
+-                              (False, True, datetime.datetime(2010, 11, 12)),
+-                              (True, True, datetime.datetime(2010, 11, 12))],
+-                 '20/12/21': [(False, False, datetime.datetime(2021, 12, 20)),
+-                              (True, False, datetime.datetime(2021, 12, 20)),
+-                              (False, True, datetime.datetime(2020, 12, 21)),
+-                              (True, True, datetime.datetime(2020, 12, 21))]}
++        cases = {'10-11-12': [(False, False, False,
++                               datetime.datetime(2012, 10, 11)),
++                              (True, False, False,
++                               datetime.datetime(2012, 11, 10)),
++                              (False, True, False,
++                               datetime.datetime(2010, 11, 12)),
++                              (True, True, False, dayfirst_yearfirst1)],
++                 '20/12/21': [(False, False, False,
++                               datetime.datetime(2021, 12, 20)),
++                              (True, False, False,
++                               datetime.datetime(2021, 12, 20)),
++                              (False, True, False,
++                               datetime.datetime(2020, 12, 21)),
++                              (True, True, True, dayfirst_yearfirst2)]}
+ 
+         tm._skip_if_no_dateutil()
+         from dateutil.parser import parse
+         for date_str, values in compat.iteritems(cases):
+-            for dayfirst, yearfirst, expected in values:
+-                result1, _, _ = tools.parse_time_string(date_str,
+-                                                        dayfirst=dayfirst,
+-                                                        yearfirst=yearfirst)
++            for dayfirst, yearfirst, is_compat, expected in values:
++
++                f = lambda x: tools.parse_time_string(x,
++                                                      dayfirst=dayfirst,
++                                                      yearfirst=yearfirst)
++
++                # we now have an invalid parse
++                if is_compat and is_compat_version:
++                    self.assertRaises(tslib.DateParseError, f, date_str)
++
++                    def f(date_str):
++                        return to_datetime(date_str, dayfirst=dayfirst,
++                                           yearfirst=yearfirst)
++
++                    self.assertRaises(ValueError, f, date_str)
++
++                    def f(date_str):
++                        return DatetimeIndex([date_str], dayfirst=dayfirst,
++                                             yearfirst=yearfirst)[0]
++
++                    self.assertRaises(ValueError, f, date_str)
++
++                    continue
++
++                result1, _, _ = f(date_str)
+ 
+                 result2 = to_datetime(date_str, dayfirst=dayfirst,
+                                       yearfirst=yearfirst)
+@@ -614,7 +653,6 @@ def test_parsers_dayfirst_yearfirst(self):
+                                         yearfirst=yearfirst)[0]
+ 
+                 # Timestamp doesn't support dayfirst and yearfirst
+-
+                 self.assertEqual(result1, expected)
+                 self.assertEqual(result2, expected)
+                 self.assertEqual(result3, expected)
diff --git a/gnu/packages/patches/ruby-symlinkfix.patch b/gnu/packages/patches/ruby-symlinkfix.patch
new file mode 100644
index 0000000000..16beecc97a
--- /dev/null
+++ b/gnu/packages/patches/ruby-symlinkfix.patch
@@ -0,0 +1,53 @@
+Fix symlinks to '..' to fix rubygems improperly expanding symlinked
+paths. Without this fix, some gems fail to install. This patch is applied in
+rubygems 2.5.2, but ruby version 2.3.1 bundles an older version of rubygems
+(2.5.1).
+
+--- a/lib/rubygems/package.rb
++++ b/lib/rubygems/package.rb
+@@ -383,7 +383,7 @@ def extract_tar_gz io, destination_dir, pattern = "*" # :nodoc:
+           FileUtils.chmod entry.header.mode, destination
+         end if entry.file?
+
+-        File.symlink(install_location(entry.header.linkname, destination_dir), destination) if entry.symlink?
++        File.symlink(entry.header.linkname, destination) if entry.symlink?
+
+         verbose destination
+       end
+diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb
+index 7848bc2..f287bd3 100644
+--- a/test/rubygems/test_gem_package.rb
++++ b/test/rubygems/test_gem_package.rb
+@@ -428,19 +428,25 @@ def test_extract_tar_gz_absolute
+                  "#{@destination} is not allowed", e.message)
+   end
+
+-  def test_extract_tar_gz_symlink_absolute
++  def test_extract_tar_gz_symlink_relative_path
++    skip 'symlink not supported' if Gem.win_platform?
++
+     package = Gem::Package.new @gem
+
+     tgz_io = util_tar_gz do |tar|
+-      tar.add_symlink 'code.rb', '/absolute.rb', 0644
++      tar.add_file    'relative.rb', 0644 do |io| io.write 'hi' end
++      tar.mkdir       'lib',         0755
++      tar.add_symlink 'lib/foo.rb', '../relative.rb', 0644
+     end
+
+-    e = assert_raises Gem::Package::PathError do
+-      package.extract_tar_gz tgz_io, @destination
+-    end
++    package.extract_tar_gz tgz_io, @destination
+
+-    assert_equal("installing into parent path /absolute.rb of " +
+-                 "#{@destination} is not allowed", e.message)
++    extracted = File.join @destination, 'lib/foo.rb'
++    assert_path_exists extracted
++    assert_equal '../relative.rb',
++                 File.readlink(extracted)
++    assert_equal 'hi',
++                 File.read(extracted)
+   end
+
+   def test_extract_tar_gz_directory
diff --git a/gnu/packages/patches/ttf2eot-cstddef.patch b/gnu/packages/patches/ttf2eot-cstddef.patch
new file mode 100644
index 0000000000..af76898e77
--- /dev/null
+++ b/gnu/packages/patches/ttf2eot-cstddef.patch
@@ -0,0 +1,12 @@
+From resolution of https://code.google.com/p/ttf2eot/issues/detail?id=26
+
+--- ttf2eot-0.0.2-2/OpenTypeUtilities.cpp	2009-04-30 04:18:46.000000000 -0500
++++ ttf2eot-0.0.2-2/OpenTypeUtilities.cpp	2016-03-31 01:06:39.109996011 -0500
+@@ -25,6 +25,7 @@
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+  */
+ 
++#include <cstddef>
+ #include <string.h>
+ #include <vector>
+ 
diff --git a/gnu/packages/patches/ttfautohint-source-date-epoch.patch b/gnu/packages/patches/ttfautohint-source-date-epoch.patch
new file mode 100644
index 0000000000..e42fdbf6b0
--- /dev/null
+++ b/gnu/packages/patches/ttfautohint-source-date-epoch.patch
@@ -0,0 +1,70 @@
+Honour an external definition of SOURCE_DATE_EPOCH when updating the embedded
+modification date in TTF/TTC files.
+
+--- a/lib/tatime.c
++++ b/lib/tatime.c
+@@ -15,6 +15,8 @@
+ 
+ #include <time.h>
+ #include <stdint.h>
++#include <errno.h>
++#include <limits.h>
+ 
+ #include "ta.h"
+ 
+@@ -27,12 +29,51 @@ TA_get_current_time(FT_ULong* high,
+ {
+   /* there have been 24107 days between January 1st, 1904 (the epoch of */
+   /* OpenType), and January 1st, 1970 (the epoch of the `time' function) */
+-  TA_ULongLong seconds_to_1970 = 24107 * 24 * 60 * 60;
+-  TA_ULongLong seconds_to_today = seconds_to_1970 + (TA_ULongLong)time(NULL);
++  const TA_ULongLong seconds_to_1970 = 24107 * 24 * 60 * 60;
++  TA_ULongLong seconds_to_build;
+ 
++  time_t now;
++  char *source_date_epoch, *endptr;
++  TA_ULongLong epoch;
++  source_date_epoch = getenv("SOURCE_DATE_EPOCH");
++  if (source_date_epoch) {
++    errno = 0;
++    epoch = strtoull(source_date_epoch, &endptr, 10);
++    if ((errno == ERANGE && (epoch == ULLONG_MAX || epoch == 0))
++	|| (errno != 0 && epoch == 0)) {
++      fprintf(stderr,
++	      "Environment variable $SOURCE_DATE_EPOCH: strtoull: %s\n",
++	      strerror(errno));
++      exit(EXIT_FAILURE);
++    }
++    if (endptr == source_date_epoch) {
++      fprintf(stderr,
++	      "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n",
++	      endptr);
++      exit(EXIT_FAILURE);
++    }
++    if (*endptr != '\0') {
++      fprintf(stderr,
++	      "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n",
++	      endptr);
++      exit(EXIT_FAILURE);
++    }
++    if (epoch > ULONG_MAX) {
++      fprintf(stderr,
++	      "Environment variable $SOURCE_DATE_EPOCH: value must be smaller "
++	      "than or equal to: %lu but was found to be: %llu \n",
++	      ULONG_MAX, epoch);
++      exit(EXIT_FAILURE);
++    }
++    now = epoch;
++  } else {
++    now = time(NULL);
++  }
+ 
+-  *high = (FT_ULong)(seconds_to_today >> 32);
+-  *low = (FT_ULong)seconds_to_today;
++  seconds_to_build = seconds_to_1970 + (TA_ULongLong)now;
++
++  *high = (FT_ULong)(seconds_to_build >> 32);
++  *low = (FT_ULong)seconds_to_build;
+ }
+ 
+ /* end of tatime.c */
diff --git a/gnu/packages/patches/woff2-libbrotli.patch b/gnu/packages/patches/woff2-libbrotli.patch
new file mode 100644
index 0000000000..ffa941cf92
--- /dev/null
+++ b/gnu/packages/patches/woff2-libbrotli.patch
@@ -0,0 +1,84 @@
+From: Eric Bavier <bavier@member.fsf.org>
+Date: Sat, 2 Apr 2016 01:31:03 -0500
+Subject: [PATCH] Build against external libbrotli.
+
+---
+ Makefile         | 20 ++++----------------
+ src/woff2_dec.cc |  2 +-
+ src/woff2_enc.cc |  2 +-
+ 3 files changed, 6 insertions(+), 18 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 92b8d54..618a751 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ OS := $(shell uname)
+ 
+-CPPFLAGS = -I./brotli/dec/ -I./brotli/enc/ -I./src
++CPPFLAGS := -I./src $(shell pkg-config --cflags libbrotlienc libbrotlidec)
+ 
+ CC ?= gcc
+ CXX ?= g++
+@@ -22,29 +22,17 @@ OUROBJ = font.o glyph.o normalize.o table_tags.o transform.o \
+          woff2_dec.o woff2_enc.o woff2_common.o woff2_out.o \
+          variable_length.o
+ 
+-BROTLI = brotli
+-ENCOBJ = $(BROTLI)/enc/*.o
+-DECOBJ = $(BROTLI)/dec/*.o
++BROTLI_LIBS := $(shell pkg-config --libs libbrotlienc libbrotlidec)
+ 
+ OBJS = $(patsubst %, $(SRCDIR)/%, $(OUROBJ))
+ EXECUTABLES=woff2_compress woff2_decompress
+ 
+ EXE_OBJS=$(patsubst %, $(SRCDIR)/%.o, $(EXECUTABLES))
+ 
+-ifeq (,$(wildcard $(BROTLI)/*))
+-  $(error Brotli dependency not found : you must initialize the Git submodule)
+-endif
+-
+ all : $(OBJS) $(EXECUTABLES)
+ 
+-$(EXECUTABLES) : $(EXE_OBJS) deps
+-	$(CXX) $(LFLAGS) $(OBJS) $(ENCOBJ) $(DECOBJ) $(SRCDIR)/$@.o -o $@
+-
+-deps :
+-	$(MAKE) -C $(BROTLI)/dec
+-	$(MAKE) -C $(BROTLI)/enc
++$(EXECUTABLES) : $(EXE_OBJS) $(OBJS)
++	$(CXX) $(LDFLAGS) $(OBJS) $(SRCDIR)/$@.o -o $@ $(BROTLI_LIBS) $(LIBS)
+ 
+ clean :
+ 	rm -f $(OBJS) $(EXE_OBJS) $(EXECUTABLES)
+-	$(MAKE) -C $(BROTLI)/dec clean
+-	$(MAKE) -C $(BROTLI)/enc clean
+diff --git a/src/woff2_dec.cc b/src/woff2_dec.cc
+index 837eede..98c01ce 100644
+--- a/src/woff2_dec.cc
++++ b/src/woff2_dec.cc
+@@ -27,7 +27,7 @@
+ #include <memory>
+ #include <utility>
+ 
+-#include "./decode.h"
++#include "brotli/dec/decode.h"
+ #include "./buffer.h"
+ #include "./port.h"
+ #include "./round.h"
+diff --git a/src/woff2_enc.cc b/src/woff2_enc.cc
+index 920c614..00d74da 100644
+--- a/src/woff2_enc.cc
++++ b/src/woff2_enc.cc
+@@ -23,7 +23,7 @@
+ #include <string>
+ #include <vector>
+ 
+-#include "./encode.h"
++#include "brotli/enc/encode.h"
+ #include "./buffer.h"
+ #include "./font.h"
+ #include "./normalize.h"
+-- 
+2.7.3
+
diff --git a/gnu/packages/patchutils.scm b/gnu/packages/patchutils.scm
index 31a735fd5d..42da56194c 100644
--- a/gnu/packages/patchutils.scm
+++ b/gnu/packages/patchutils.scm
@@ -48,8 +48,7 @@
       (sha256
        (base32
         "0g5df00cj4nczrmr4k791l7la0sq2wnf8rn981fsrz1f3d2yix4i"))
-      (patches
-       (list (search-patch "patchutils-xfail-gendiff-tests.patch")))))
+      (patches (search-patches "patchutils-xfail-gendiff-tests.patch"))))
     (build-system gnu-build-system)
     (inputs `(("perl" ,perl)))
     (arguments
@@ -178,24 +177,25 @@ refreshed, and more.")
     (license gpl2+)))
 
 (define-public patches
-  (let ((commit "26d7dbc"))
+  (let ((commit "ef1b8a7d954b82ed4af3a08fd63d2085d19090ef"))
     (package
       (name "patches")
-      (version (string-append "0.0." commit))
+      (home-page "https://github.com/stefanha/patches")
+      (version (string-append "0.0-1." (string-take commit 7)))
       (source (origin
                 (method git-fetch)
                 (uri (git-reference
-                      (url "https://github.com/aliguori/patches")
+                      (url home-page)
                       (commit commit)))
                 (sha256
                  (base32
-                  "1bah6y84nlii5yif189ns28dz1m9vmsyw66jyk2vr5yf0njf7mzh"))))
+                  "11rdmhv0l1s8nqb20ywmw2zqizczch2p62qf9apyx5wqgxlnjshk"))
+                (file-name (string-append name "-"version "-checkout"))))
       (build-system python-build-system)
       (inputs `(("python-notmuch" ,python2-notmuch)))
       (arguments
        `(#:tests? #f                             ;no "test" target
-                  #:python ,python-2))           ;not compatible with Python 3
-      (home-page "https://github.com/aliguori/patches")
+         #:python ,python-2))                    ;not compatible with Python 3
       (synopsis "Patch tracking tool")
       (description
        "'Patches' is a patch-tracking tool initially written for the QEMU
diff --git a/gnu/packages/pcre.scm b/gnu/packages/pcre.scm
index cb6eddddb7..248242af4d 100644
--- a/gnu/packages/pcre.scm
+++ b/gnu/packages/pcre.scm
@@ -31,6 +31,7 @@
   (package
    (name "pcre")
    (version "8.38")
+   (replacement pcre-fixed)
    (source (origin
             (method url-fetch)
             (uri (list
@@ -68,10 +69,17 @@ POSIX regular expression API.")
    (license license:bsd-3)
    (home-page "http://www.pcre.org/")))
 
+(define pcre-fixed                                ;for CVE-2016-3191
+  (package
+    (inherit pcre)
+    (source (origin
+              (inherit (package-source pcre))
+              (patches (search-patches "pcre-CVE-2016-3191.patch"))))))
+
 (define-public pcre2
   (package
     (name "pcre2")
-    (version "10.20")
+    (version "10.21")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://sourceforge/pcre/pcre2/"
@@ -79,7 +87,7 @@ POSIX regular expression API.")
 
               (sha256
                (base32
-                "0yj8mm9ll9zj3v47rvmmqmr1ybxk72rr2lym3rymdsf905qjhbik"))))
+                "1q6lrj9b08l1q39vxipb0fi88x6ybvkr6439h8bjb9r8jd81fsn6"))))
    (build-system gnu-build-system)
    (inputs `(("bzip2" ,bzip2)
              ("readline" ,readline)
diff --git a/gnu/packages/pdf.scm b/gnu/packages/pdf.scm
index e8e6993a9c..8f9f5dd503 100644
--- a/gnu/packages/pdf.scm
+++ b/gnu/packages/pdf.scm
@@ -53,6 +53,7 @@
   (package
    (name "poppler")
    (version "0.37.0")
+   (replacement poppler/fixed)
    (source (origin
             (method url-fetch)
             (uri (string-append "https://poppler.freedesktop.org/poppler-"
@@ -104,6 +105,13 @@
    (license license:gpl2+)
    (home-page "http://poppler.freedesktop.org/")))
 
+(define poppler/fixed
+  (package
+    (inherit poppler)
+    (source (origin
+              (inherit (package-source poppler))
+              (patches (search-patches "poppler-CVE-2015-8868.patch"))))))
+
 (define-public poppler-qt4
   (package (inherit poppler)
    (name "poppler-qt4")
@@ -336,9 +344,8 @@ by using the poppler rendering engine.")
               (sha256
                (base32
                 "1rywx09qn6ap5hb1z31wxby4lzdrqdbldm51pjk1ifflr37xwirk"))
-              (patches
-               (list
-                (search-patch "zathura-plugindir-environment-variable.patch")))))
+              (patches (search-patches
+                        "zathura-plugindir-environment-variable.patch"))))
     (native-inputs `(("pkg-config" ,pkg-config)
                      ("gettext" ,gnu-gettext)))
     (inputs `(("girara" ,girara)
diff --git a/gnu/packages/perl.scm b/gnu/packages/perl.scm
index 41bcd7da84..1b5ca134fe 100644
--- a/gnu/packages/perl.scm
+++ b/gnu/packages/perl.scm
@@ -47,14 +47,14 @@
              (sha256
               (base32
                "09wg24w5syyafyv87l6z8pxwz4bjgcdj996bx5844k6m9445sirb"))
-             (patches (map search-patch
-                           '("perl-no-sys-dirs.patch"
-                             "perl-autosplit-default-time.patch"
-                             "perl-source-date-epoch.patch"
-                             "perl-deterministic-ordering.patch"
-                             "perl-no-build-time.patch"
-                             "perl-CVE-2015-8607.patch"
-                             "perl-CVE-2016-2381.patch")))))
+             (patches (search-patches
+                       "perl-no-sys-dirs.patch"
+                       "perl-autosplit-default-time.patch"
+                       "perl-source-date-epoch.patch"
+                       "perl-deterministic-ordering.patch"
+                       "perl-no-build-time.patch"
+                       "perl-CVE-2015-8607.patch"
+                       "perl-CVE-2016-2381.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:tests? #f
@@ -3128,7 +3128,7 @@ installation version 5.005 or newer.")
        (sha256
         (base32
          "1px6qmszmfc69v36vd8d92av4nkrif6xf4nrj3xv647xwi2svwmk"))
-       (patches (list (search-patch "perl-module-pluggable-search.patch")))))
+       (patches (search-patches "perl-module-pluggable-search.patch"))))
     (build-system perl-build-system)
     (home-page "http://search.cpan.org/dist/Module-Pluggable")
     (synopsis "Give your Perl module the ability to have plugins")
diff --git a/gnu/packages/plotutils.scm b/gnu/packages/plotutils.scm
index e9a247142d..3fdd539835 100644
--- a/gnu/packages/plotutils.scm
+++ b/gnu/packages/plotutils.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2016 Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -51,7 +52,7 @@
              (sha256
               (base32
                "1arkyizn5wbgvbh53aziv3s6lmd3wm9lqzkhxb3hijlp1y124hjg"))
-             (patches (list (search-patch "plotutils-libpng-jmpbuf.patch")))
+             (patches (search-patches "plotutils-libpng-jmpbuf.patch"))
              (modules '((guix build utils)))
              (snippet
               ;; Force the use of libXaw7 instead of libXaw.  When not doing
@@ -171,15 +172,14 @@ colors, styles, options and details.")
 (define-public asymptote
   (package
     (name "asymptote")
-    (version "2.35")
+    (version "2.37")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://sourceforge/asymptote/"
                                   version "/asymptote-" version ".src.tgz"))
               (sha256
                (base32
-                "11f28vxw0ybhvl7vxmqcdwvw7y6gz55ykw9ybgzb2px6lsvgag7z"))
-              (patches (list (search-patch "asymptote-gsl2.patch")))))
+                "16nh02m52mk9a53i8wc6l9vg710gnzr3lfbypcbvamghvaj0458i"))))
     (build-system gnu-build-system)
     ;; Note: The 'asy' binary retains a reference to docdir for use with its
     ;; "help" command in interactive mode, so adding a "doc" output is not
@@ -206,13 +206,19 @@ colors, styles, options and details.")
              (string-append "--with-context="
                             (assoc-ref %outputs "out")
                             "/share/texmf/tex/context/third"))
-       #:phases (modify-phases %standard-phases
-                  (add-before 'build 'patch-pdf-viewer
-                    (lambda _
-                      ;; Default to a free pdf viewer
-                      (substitute* "settings.cc"
-                        (("defaultPDFViewer=\"acroread\"")
-                         "defaultPDFViewer=\"gv\"")))))))
+       #:phases
+       (modify-phases %standard-phases
+         (add-before 'build 'patch-pdf-viewer
+           (lambda _
+             ;; Default to a free pdf viewer
+             (substitute* "settings.cc"
+               (("defaultPDFViewer=\"acroread\"")
+                "defaultPDFViewer=\"gv\""))))
+         (add-before 'check 'set-HOME
+           ;; Some tests require write access to $HOME, otherwise leading to
+           ;; "failed to create directory /homeless-shelter/.asy" error.
+           (lambda _
+             (setenv "HOME" "/tmp"))))))
     (home-page "http://asymptote.sourceforge.net")
     (synopsis "Script-based vector graphics language")
     (description
diff --git a/gnu/packages/polkit.scm b/gnu/packages/polkit.scm
index 4f21612804..08b753a6cf 100644
--- a/gnu/packages/polkit.scm
+++ b/gnu/packages/polkit.scm
@@ -48,7 +48,7 @@
              (sha256
               (base32
                "109w86kfqrgz83g9ivggplmgc77rz8kx8646izvm2jb57h4rbh71"))
-             (patches (list (search-patch "polkit-drop-test.patch")))
+             (patches (search-patches "polkit-drop-test.patch"))
              (modules '((guix build utils)))
              (snippet
               '(begin
diff --git a/gnu/packages/pretty-print.scm b/gnu/packages/pretty-print.scm
index 7c0f50d467..a1692dd4de 100644
--- a/gnu/packages/pretty-print.scm
+++ b/gnu/packages/pretty-print.scm
@@ -191,7 +191,8 @@ their syntactic role.  It supports over 150 different languages and it can
 output to 8 different formats, including HTML, LaTeX and ODF.  It can also
 output to ANSI color escape sequences, so that highlighted source code can be
 seen in a terminal.")
-    (license gpl3+)))
+    (license gpl3+)
+    (properties '((ftp-directory . "/gnu/src-highlite")))))
 
 (define-public astyle
   (package
diff --git a/gnu/packages/pulseaudio.scm b/gnu/packages/pulseaudio.scm
index 8c37b2a3f1..b2b0508e58 100644
--- a/gnu/packages/pulseaudio.scm
+++ b/gnu/packages/pulseaudio.scm
@@ -131,9 +131,9 @@ rates.")
               '(substitute* "src/daemon/default.pa.in"
                  (("load-module module-console-kit" all)
                   (string-append "#" all "\n"))))
-             (patches
-              (list (search-patch "pulseaudio-fix-mult-test.patch")
-                    (search-patch "pulseaudio-longer-test-timeout.patch")))))
+             (patches (search-patches
+                       "pulseaudio-fix-mult-test.patch"
+                       "pulseaudio-longer-test-timeout.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags (list "--localstatedir=/var" ;"--sysconfdir=/etc"
diff --git a/gnu/packages/python.scm b/gnu/packages/python.scm
index 1db749bff1..ef06c89298 100644
--- a/gnu/packages/python.scm
+++ b/gnu/packages/python.scm
@@ -1,13 +1,13 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
-;;; Copyright © 2013, 2014, 2015 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2013, 2014, 2015, 2016 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2014, 2015 Federico Beffa <beffa@fbengineering.ch>
 ;;; Copyright © 2015 Omar Radwan <toxemicsquire4@gmail.com>
 ;;; Copyright © 2015 Pierre-Antoine Rault <par@rigelk.eu>
-;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015, 2016 Christopher Allan Webber <cwebber@dustycloud.org>
 ;;; Copyright © 2015 Eric Dvorsak <eric@dvorsak.fr>
 ;;; Copyright © 2015, 2016 David Thompson <davet@gnu.org>
@@ -37,11 +37,12 @@
 (define-module (gnu packages python)
   #:use-module ((guix licenses)
                 #:select (asl2.0 bsd-4 bsd-3 bsd-2 non-copyleft cc0 x11 x11-style
-                          gpl2 gpl2+ gpl3+ lgpl2.0+ lgpl2.1 lgpl2.1+ lgpl3+ agpl3+
+                          gpl2 gpl2+ gpl3 gpl3+ lgpl2.0+ lgpl2.1 lgpl2.1+ lgpl3+ agpl3+
                           isc mpl2.0 psfl public-domain repoze unlicense x11-style
                           zpl2.1))
   #:use-module ((guix licenses) #:select (expat zlib) #:prefix license:)
   #:use-module (gnu packages)
+  #:use-module (gnu packages algebra)
   #:use-module (gnu packages attr)
   #:use-module (gnu packages backup)
   #:use-module (gnu packages compression)
@@ -77,6 +78,8 @@
   #:use-module (gnu packages xdisorg)
   #:use-module (gnu packages zip)
   #:use-module (gnu packages tcl)
+  #:use-module (gnu packages bdw-gc)
+  #:use-module (gnu packages pcre)
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix git-download)
@@ -99,10 +102,9 @@
       (sha256
        (base32
         "0iiz844riiznsyhhyy962710pz228gmhv8qi3yk4w4jhmx2lqawn"))
-      (patches (map search-patch
-                    '("python-2.7-search-paths.patch"
-                      "python-2-deterministic-build-info.patch"
-                      "python-2.7-source-date-epoch.patch")))
+      (patches (search-patches "python-2.7-search-paths.patch"
+                               "python-2-deterministic-build-info.patch"
+                               "python-2.7-source-date-epoch.patch"))
       (modules '((guix build utils)))
       ;; suboptimal to delete failing tests here, but if we delete them in the
       ;; arguments then we need to make sure to strip out that phase when it
@@ -255,12 +257,12 @@ data types.")
               (method url-fetch)
               (uri (string-append "https://www.python.org/ftp/python/"
                                   version "/Python-" version ".tar.xz"))
-              (patches (map search-patch
-                            '("python-fix-tests.patch"
-                              ;; XXX Try removing this patch for python > 3.4.3
-                              "python-disable-ssl-test.patch"
-                              "python-3-deterministic-build-info.patch"
-                              "python-3-search-paths.patch")))
+              (patches (search-patches
+                        "python-fix-tests.patch"
+                        ;; XXX Try removing this patch for python > 3.4.3
+                        "python-disable-ssl-test.patch"
+                        "python-3-deterministic-build-info.patch"
+                        "python-3-search-paths.patch"))
               (patch-flags '("-p0"))
               (sha256
                (base32
@@ -441,17 +443,14 @@ John the Ripper).")
 (define-public python-paramiko
   (package
     (name "python-paramiko")
-    (version "1.15.2")
+    (version "1.16.0")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/p/paramiko/paramiko-"
-             version
-             ".tar.gz"))
+       (uri (pypi-uri "paramiko" version))
        (sha256
         (base32
-         "0mbfzm9zlrz6mla9xakrm8wkll3x035f9rj3c5pbgjzfldqscmjg"))))
+         "14k8z7ndc3zk5xivnm4d8lncchx475ll5izpf8vmfbq7rp9yp5rj"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
@@ -474,22 +473,18 @@ Python interface around SSH networking concepts.")
 (define-public python-httplib2
   (package
     (name "python-httplib2")
-    (version "0.9.1")
+    (version "0.9.2")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/h/httplib2/httplib2-"
-             version
-             ".tar.gz"))
+       (uri (pypi-uri "httplib2" version))
        (sha256
         (base32
-         "1xc3clbrf77r0600kja71j7hk1218sjiq0gfmb8vjdajka8kjqxw"))))
+         "126rsryvw9vhbf3qmsfw9lf4l4xm2srmgs439lgma4cpag4s3ay3"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
-    (home-page
-     "https://github.com/jcgregorio/httplib2")
+    (home-page "https://github.com/jcgregorio/httplib2")
     (synopsis "Comprehensive HTTP client library")
     (description
      "A comprehensive HTTP client library supporting many features left out of
@@ -536,17 +531,14 @@ making them easy to handle and incorporate into other protocols.")
 (define-public python-ccm
   (package
     (name "python-ccm")
-    (version "2.0.4.1")
+    (version "2.1.6")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/c/ccm/ccm-"
-             version
-             ".tar.gz"))
+       (uri (pypi-uri "ccm" version))
        (sha256
         (base32
-         "199jw221albs2iv6xczczq88fxnh0aw8hzmys8qkbzkd99dssng9"))))
+         "177dfxsmk3k4cih6fh6v8d91bh4nqx7ns6pc07w7m7i3cvdx3c8n"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
@@ -565,14 +557,14 @@ Cassandra cluster on localhost.")
 (define-public python-pytz
   (package
     (name "python-pytz")
-    (version "2015.7")
+    (version "2016.3")
     (source
      (origin
       (method url-fetch)
-      (uri (pypi-uri "pytz" version))
+      (uri (pypi-uri "pytz" version ".tar.bz2"))
       (sha256
        (base32
-        "1spgdfp1ssya7v3kww7zp71xpj437skpqazcvqr3kr1p1brnw9lr"))))
+        "1mjmrkk4vc5xzppw7fm0pli1nnbj57cvqv7jjv5whcmccyhxz4y1"))))
     (build-system python-build-system)
     (arguments `(#:tests? #f)) ; no test target
     (home-page "http://pythonhosted.org/pytz")
@@ -589,14 +581,14 @@ using Python 2.4 or higher and provides access to the Olson timezone database.")
 (define-public python-babel
   (package
     (name "python-babel")
-    (version "2.1.1")
+    (version "2.3.2")
     (source
      (origin
       (method url-fetch)
       (uri (pypi-uri "Babel" version))
       (sha256
        (base32
-        "0j2jgfzj1a2m39pm2qc36fzr7a6p5ybwndi0xdzhi2p8zw7dbdkz"))))
+        "0k43pi0p1dwpds2w0km3fw92wixzxv2vw7p09capxmjz5cfh23lw"))))
     (build-system python-build-system)
     (inputs
      `(("python-pytz" ,python-pytz)
@@ -648,15 +640,14 @@ and verifies that it matches the intended target hostname.")
 (define-public python-h5py
   (package
     (name "python-h5py")
-    (version "2.4.0")
+    (version "2.6.0")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "https://pypi.python.org/packages/source/h/h5py/h5py-"
-                          version ".tar.gz"))
+      (uri (pypi-uri "h5py" version))
       (sha256
        (base32
-        "0q4f9l8grf6pwp64xbv8bmyxx416s7h4522nnxac056ap3savbps"))))
+        "0df46dg7i7xfking9lp221bfm8dbl974yvlrbi1w7r6m61ac7bxj"))))
     (build-system python-build-system)
     (arguments
      `(#:tests? #f ; no test target
@@ -677,9 +668,11 @@ and verifies that it matches the intended target hostname.")
     (propagated-inputs
      `(("python-numpy" ,python-numpy)))
     (inputs
-     `(("hdf5" ,hdf5)))
+     `(("hdf5" ,hdf5)
+       ("python-six" ,python-six)))
     (native-inputs
-     `(("python-cython" ,python-cython)))
+     `(("python-cython" ,python-cython)
+       ("python-pkgconfig" ,python-pkgconfig)))
     (home-page "http://www.h5py.org/")
     (synopsis "Read and write HDF5 files from Python")
     (description
@@ -688,16 +681,11 @@ HDF5 library from Python.  The low-level interface is intended to be a
 complete wrapping of the HDF5 API, while the high-level component supports
 access to HDF5 files, datasets and groups using established Python and NumPy
 concepts.")
-    (license bsd-3)))
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-h5py))))))
 
 (define-public python2-h5py
-  (let ((h5py (package-with-python2 python-h5py)))
-    (package (inherit h5py)
-      (propagated-inputs
-       `(("python2-numpy" ,python2-numpy)
-         ,@(alist-delete
-            "python-numpy"
-            (package-propagated-inputs h5py)))))))
+  (package-with-python2 (strip-python2-variant python-h5py)))
 
 (define-public python-lockfile
   (package
@@ -837,19 +825,17 @@ etc.).  The package is structured to make adding new modules easy.")
 (define-public python-keyring
   (package
     (name "python-keyring")
-    (version "5.7.1")
+    (version "8.7")
     (source
      (origin
       (method url-fetch)
       (uri (pypi-uri "keyring" version))
       (sha256
        (base32
-        "1h7a1r9ick7wdd0xb5p63413nvjadna2xawrsvmklsl5ddhm5wrx"))))
+        "0482rmi2x6p78wl2kz8qzyq21xz1sbbfwnv5x7dggar4vkwxhzfx"))))
     (build-system python-build-system)
     (native-inputs
-     `(("python-setuptools" ,python-setuptools)
-       ("python-setuptools-scm" ,python-setuptools-scm)
-       ("python-mock" ,python-mock)))
+     `(("python-setuptools-scm" ,python-setuptools-scm)))
     (inputs
      `(("python-pycrypto" ,python-pycrypto)))
     (arguments
@@ -861,13 +847,15 @@ etc.).  The package is structured to make adding new modules easy.")
 service from python.  It can be used in any application that needs safe
 password storage.")
     ;; "MIT" and PSF dual license
-    (license x11)))
+    (license x11)
+    (properties `((python2-variant . ,(delay python2-keyring))))))
 
 (define-public python2-keyring
-  (let ((keyring (package-with-python2 python-keyring)))
-    (package (inherit keyring)
-      (inputs
-       `(("python2-pycrypto" ,python2-pycrypto))))))
+  (let ((base (package-with-python2 (strip-python2-variant python-keyring))))
+    (package
+      (inherit base)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs base))))))
 
 (define-public python-six
   (package
@@ -899,28 +887,31 @@ Python file, so it can be easily copied into your project.")
 (define-public python-dateutil-2
   (package
     (name "python-dateutil")
-    (version "2.4.2")
+    (version "2.5.2")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "https://pypi.python.org/packages/source/p/"
-                          name "/" name "-" version ".tar.gz"))
+      (uri (pypi-uri "python-dateutil" version))
       (sha256
        (base32
-        "0ggbm2z72p0nwjqgvpw8s5bqzwayqiqv2iws0x2a605m3mf4959y"))))
+        "0jrfpcgvgya6hs45dhrd9yiqgdgz9qp9aa07zsw8gqgn8zphff86"))))
     (build-system python-build-system)
     (inputs
-     `(("python-setuptools" ,python-setuptools)
-       ("python-six" ,python-six)))
+     `(("python-six" ,python-six)))
     (home-page "http://labix.org/python-dateutil")
     (synopsis "Extensions to the standard datetime module")
     (description
      "The dateutil module provides powerful extensions to the standard
 datetime module, available in Python 2.3+.")
-    (license bsd-3)))
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-dateutil-2))))))
 
 (define-public python2-dateutil-2
-  (package-with-python2 python-dateutil-2))
+  (let ((base (package-with-python2 (strip-python2-variant python-dateutil-2))))
+    (package
+      (inherit base)
+      (inputs `(("python2-setuptools" ,python2-setuptools)
+                ,@(package-inputs base))))))
 
 (define-public python-dateutil
   (package
@@ -950,27 +941,32 @@ datetime module, available in Python 2.3+.")
 (define-public python-parsedatetime
   (package
     (name "python-parsedatetime")
-    (version "1.5")
+    (version "2.1")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "https://pypi.python.org/packages/source/p/"
-                          "parsedatetime/parsedatetime-" version ".tar.gz"))
+      (uri (pypi-uri "parsedatetime" version))
       (sha256
        (base32
-        "1as0mm4ql3z0324nc9bys2s1ngh507i317p16b79rx86wlmvx9ix"))))
+        "0bdgyw6y3v7bcxlx0p50s8drxsh5bb5cy2afccqr3j90amvpii8p"))))
     (build-system python-build-system)
     (native-inputs
-     `(("python-setuptools" ,python-setuptools)))
+     `(("python-nose" ,python-nose)
+       ("python-pyicu" ,python-pyicu)))
     (home-page "http://github.com/bear/parsedatetime/")
     (synopsis
      "Parse human-readable date/time text")
     (description
      "Parse human-readable date/time text.")
-    (license asl2.0)))
+    (license asl2.0)
+    (properties `((python2-variant . ,(delay python2-parsedatetime))))))
 
 (define-public python2-parsedatetime
-  (package-with-python2 python-parsedatetime))
+  (let ((base (package-with-python2 (strip-python2-variant python-parsedatetime))))
+    (package
+      (inherit base)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs base))))))
 
 (define-public python-pandas
   (package
@@ -981,11 +977,14 @@ datetime module, available in Python 2.3+.")
        (method url-fetch)
        (uri (pypi-uri "pandas" version))
        (sha256
-        (base32 "050qw0ap5bhyv5flp78x3lcq1dlminl3xaj6kbrm0jqmx0672xf9"))))
+        (base32 "050qw0ap5bhyv5flp78x3lcq1dlminl3xaj6kbrm0jqmx0672xf9"))
+       (patches (search-patches
+                 "python-pandas-fix-tslib-test-failure.patch"))))
     (build-system python-build-system)
     (propagated-inputs
-     `(("python-numpy" ,python-numpy)
-       ("python-pytz" ,python-pytz)
+     `(("python-numpy" ,python-numpy)))
+    (inputs
+     `(("python-pytz" ,python-pytz)
        ("python-dateutil" ,python-dateutil-2)))
     (native-inputs
      `(("python-nose" ,python-nose)
@@ -1011,16 +1010,16 @@ doing practical, real world data analysis in Python.")
 (define-public python-tzlocal
   (package
     (name "python-tzlocal")
-    (version "1.2")
+    (version "1.2.2")
     (source
      (origin
       (method url-fetch)
       (uri (pypi-uri "tzlocal" version))
       (sha256
        (base32
-        "12wsw2fl3adrqrwghasld57bhqdrzn0crblqrci1p5acd0ni53s3"))))
+        "0paj7vlsb0np8b5sp4bv64wxv7qk2piyp7xg29pkhdjwsbls9fnb"))))
     (build-system python-build-system)
-    (propagated-inputs `(("python-pytz" ,python-pytz)))
+    (inputs `(("python-pytz" ,python-pytz)))
     (home-page "https://github.com/regebro/tzlocal")
     (synopsis
      "Local timezone information for Python")
@@ -1249,9 +1248,8 @@ commands.")
               (sha256
                (base32
                 "17ni00p08gp5lkxlrrcnvi3x09fmajnlbz4da03qcgl9q21ym4jd"))
-              (patches (map search-patch
-                            (list "pybugz-stty.patch"
-                                  "pybugz-encode-error.patch")))))
+              (patches (search-patches "pybugz-stty.patch"
+                                       "pybugz-encode-error.patch"))))
     (build-system python-build-system)
     (arguments
      `(#:python ,python-2                         ; SyntaxError with Python 3
@@ -1320,15 +1318,14 @@ backported for previous versions of Python from 2.4 to 3.3.")
 (define-public python-parse
   (package
     (name "python-parse")
-    (version "1.6.4")
+    (version "1.6.6")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "https://pypi.python.org/packages/source/p/"
-                          "parse/parse-" version ".tar.gz"))
+      (uri (pypi-uri "parse" version))
       (sha256
        (base32
-        "0m30q64l6szl7s9mhvqy64w2fdhdn8lb91fmacjiwbv3479cmk57"))))
+        "0y31i3mwgv35qn0kzzjn9q8jqfdqmbi6sr6yfvn8rq4lqjm5lhvi"))))
     (build-system python-build-system)
     (arguments
      `(#:phases
@@ -1557,30 +1554,33 @@ and many external plugins.")
 (define-public python-pytest-cov
   (package
     (name "python-pytest-cov")
-    (version "2.2.0")
+    (version "2.2.1")
     (source
       (origin
         (method url-fetch)
         (uri (pypi-uri "pytest-cov" version))
         (sha256
-          (base32
-           "1lf9jsmhqk5nc4w3kzwglmdzjvmi7ajvrsnwv826j3bn0wzx8c92"))))
+         (base32
+          "1yl4nbhzfgsxqlsyk4clafgp9x11zvgrkprm9i2p3fgkwx9jxcm8"))))
     (build-system python-build-system)
-    (propagated-inputs
+    (inputs
      `(("python-coverage" ,python-coverage)
        ("python-pytest" ,python-pytest)))
-    (native-inputs
-     `(("python-setuptools" ,python-setuptools)))
     (home-page "https://github.com/pytest-dev/pytest-cov")
     (synopsis "Pytest plugin for measuring coverage")
     (description
      "Pytest-cov produces coverage reports.  It supports centralised testing and
 distributed testing in both @code{load} and @code{each} modes.  It also
 supports coverage of subprocesses.")
-  (license license:expat)))
+  (license license:expat)
+  (properties `((python2-variant . ,(delay python2-pytest-cov))))))
 
 (define-public python2-pytest-cov
-  (package-with-python2 python-pytest-cov))
+  (let ((base (package-with-python2 (strip-python2-variant python-pytest-cov))))
+    (package
+      (inherit base)
+      (inputs `(("python2-setuptools" ,python2-setuptools)
+                ,@(package-inputs base))))))
 
 (define-public python-pytest-runner
   (package
@@ -1589,9 +1589,7 @@ supports coverage of subprocesses.")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "https://pypi.python.org/packages/source/p/"
-                           "pytest-runner/pytest-runner-"
-                           version ".tar.gz"))
+       (uri (pypi-uri "pytest-runner" version))
        (sha256
         (base32
          "1nwcqx0l3fv52kv8526wy8ypzghbq96c96di318d98d3wh7a8xg7"))))
@@ -1609,14 +1607,22 @@ supports coverage of subprocesses.")
             #t)))))
     (native-inputs
      `(("python-pytest" ,python-pytest)
-       ("python-setuptools" ,python-setuptools)
        ("python-setuptools-scm" ,python-setuptools-scm)))
-    (home-page "https://bitbucket.org/pytest-dev/pytest-runner")
+    (home-page "https://github.com/pytest-dev/pytest-runner")
     (synopsis "Invoke py.test as a distutils command")
     (description
      "This package provides a @command{pytest-runner} command that
 @file{setup.py} files can use to run tests.")
-    (license license:expat)))
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-pytest-runner))))))
+
+(define-public python2-pytest-runner
+  (let ((base (package-with-python2
+                (strip-python2-variant python-pytest-runner))))
+    (package
+      (inherit base)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs base))))))
 
 (define-public python2-pytest-runner
   (package-with-python2 python-pytest-runner))
@@ -1635,10 +1641,10 @@ supports coverage of subprocesses.")
     (build-system python-build-system)
     (native-inputs
      `(("unzip" ,unzip)
-       ("python-setuptools" ,python-setuptools)
        ("python-setuptools-scm" ,python-setuptools-scm)))
-    (propagated-inputs
-     `(("python-execnet" ,python-execnet)
+    (inputs
+     `(("python-apipkg" ,python-apipkg)
+       ("python-execnet" ,python-execnet)
        ("python-pytest" ,python-pytest)
        ("python-py" ,python-py)))
     (home-page
@@ -1652,10 +1658,16 @@ to run tests repeatedly when failed, and the ability to run tests on multiple
 Python interpreters or platforms.  It uses rsync to copy the existing
 program code to a remote location, executes there, and then syncs the
 result back.")
-    (license license:expat)))
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-pytest-xdist))))))
 
 (define-public python2-pytest-xdist
-  (package-with-python2 python-pytest-xdist))
+  (let ((base (package-with-python2
+                (strip-python2-variant python-pytest-xdist))))
+    (package
+      (inherit base)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs base))))))
 
 (define-public python-scripttest
   (package
@@ -2196,9 +2208,8 @@ installed with a newer @code{pip} or with wheel's own command line utility.")
                "0zsqrzlybf25xscgi7ja4s48y2abf9wvjkn47wh984qgs1fq2xy5"))))
     (build-system python-build-system)
     (native-inputs
-     `(("python-setuptools" ,python-setuptools)))
-    (propagated-inputs
-     `(("python-py" ,python-py)
+     `(("python-setuptools" ,python-setuptools)
+       ("python-py" ,python-py)
        ("python-pytest" ,python-pytest)
        ("python-pytest-cov" ,python-pytest-cov)
        ("python-wheel" ,python-wheel)))
@@ -2344,8 +2355,7 @@ somewhat intelligeble.")
                 "1bfrj70vdjxjw74khbyh6f0dksv7p5rh2346jnlrffyacd3gwjzg"))))
     (build-system python-build-system)
     (native-inputs
-     `(("python-setuptools" ,python-setuptools)
-       ("python-coverage" ,python-coverage)
+     `(("python-coverage" ,python-coverage)
        ("python-nose" ,python-nose)
        ("python-mock" ,python-mock)))
     (inputs
@@ -2357,17 +2367,16 @@ somewhat intelligeble.")
     (description
      "Oauthlib is a generic, spec-compliant, thorough implementation of the
 OAuth request-signing logic.")
-    (license bsd-3)))
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-oauthlib))))))
 
 (define-public python2-oauthlib
-  (let ((base (package-with-python2 python-oauthlib)))
+  (let ((base (package-with-python2 (strip-python2-variant python-oauthlib))))
     (package
       (inherit base)
-      (inputs
-       `(("python2-unittest2" ,python2-unittest2)
-         ("python2-cryptography" ,python2-cryptography)
-         ,@(alist-delete "python-cryptography"
-	                 (package-inputs base)))))))
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ("python2-unittest2" ,python2-unittest2)
+                       ,@(package-native-inputs base))))))
 
 (define-public python-itsdangerous
   (package
@@ -2383,17 +2392,21 @@ OAuth request-signing logic.")
         (base32
          "06856q6x675ly542ig0plbqcyab6ksfzijlyf1hzhgg3sgwgrcyb"))))
     (build-system python-build-system)
-    (inputs
-     `(("python-setuptools" ,python-setuptools)))
     (home-page "http://github.com/mitsuhiko/itsdangerous")
     (synopsis "Python library for passing data to/from untrusted environments")
     (description
      "Itsdangerous provides various helpers to pass trusted data to untrusted
 environments and back.")
-    (license bsd-3)))
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-itsdangerous))))))
 
 (define-public python2-itsdangerous
-  (package-with-python2 python-itsdangerous))
+  (let ((base (package-with-python2
+                (strip-python2-variant python-itsdangerous))))
+    (package
+      (inherit base)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs base))))))
 
 (define-public python-pyyaml
   (package
@@ -2676,31 +2689,20 @@ sources.")
 (define-public python-feedgenerator
   (package
     (name "python-feedgenerator")
-    (version "20150710.97185b7")
+    (version "1.8")
     (source
-     ;; Using the git checkout for now because license file not added till
-     ;; https://github.com/dmdm/feedgenerator-py3k/commit/97185b7566c240c4bf5ed80db7d6c271204dab39
      (origin
-       (method git-fetch)
-       (uri (git-reference
-             (url "https://github.com/dmdm/feedgenerator-py3k.git")
-             (commit "97185b7566c240c4bf5ed80db7d6c271204dab39")))
+       (method url-fetch)
+       (uri (pypi-uri "feedgenerator" version))
        (sha256
         (base32
-         "0dbd6apij5j1923ib905x0srgcyls4wlabqlwp4dzkwmksvnrr2a"))))
-    (arguments
-     `(;; With standard flags, the install phase attempts to create a zip'd
-       ;; egg file, and fails with an error: 'ZIP does not support timestamps
-       ;; before 1980'
-       #:configure-flags '("--single-version-externally-managed"
-                           "--record=feedgenerator.txt")))
+         "0mkimp1fpdan4p3882vzcws4l594k71ich4g0wq97jbra7p602n0"))))
     (build-system python-build-system)
-    (inputs
+    (native-inputs
      `(("python-setuptools" ,python-setuptools)
        ("python-pytz" ,python-pytz)
        ("python-six" ,python-six)))
-    (home-page
-     "https://github.com/dmdm/feedgenerator-py3k.git")
+    (home-page "https://github.com/getpelican/feedgenerator")
     (synopsis
      "Standalone version of Django's Atom/RSS feed generator")
     (description
@@ -2750,9 +2752,7 @@ interested parties to subscribe to events, or \"signals\".")
         (base32
          "1hn94rb4q3zmcq16in055xikal4dba5hfx3zznq7warllcgc9f8k"))))
     (build-system python-build-system)
-    (native-inputs
-     `(("python-setuptools" ,python-setuptools)))
-    (propagated-inputs
+    (inputs
      `(("python-feedgenerator" ,python-feedgenerator)
        ("python-jinja2" ,python-jinja2)
        ("python-pygments" ,python-pygments)
@@ -2942,14 +2942,14 @@ is designed to have a low barrier to entry.")
 (define-public python-cython
   (package
     (name "python-cython")
-    (version "0.23.4")
+    (version "0.24")
     (source
      (origin
        (method url-fetch)
        (uri (pypi-uri "Cython" version))
        (sha256
         (base32
-         "13hdffhd37mx3gjby018xl179jaj957fy7kzi01crmimxvn2zi7y"))))
+         "1wd3q97gia3zhsgcdlvxh26hkrf3m53i6r1l4g0yya119264vr3d"))))
     (build-system python-build-system)
     ;; we need the full python package and not just the python-wrapper
     ;; because we need libpython3.3m.so
@@ -3279,7 +3279,7 @@ transcendental functions).")
        (sha256
         (base32
          "1dn05cvd0g984lzhh72wa0z93psgwshbbg93fkab6slx5m3l95av"))
-       (patches (list (search-patch "matplotlib-setupext-tk.patch")))))
+       (patches (search-patches "matplotlib-setupext-tk.patch"))))
     (build-system python-build-system)
     (outputs '("out" "doc"))
     (propagated-inputs ; the following packages are all needed at run time
@@ -3409,22 +3409,26 @@ toolkits.")
 (define-public python2-pysnptools
   (package
     (name "python2-pysnptools")
-    (version "0.3.5")
+    (version "0.3.9")
     (source
      (origin
        (method url-fetch)
        (uri (pypi-uri "pysnptools" version ".zip"))
        (sha256
         (base32
-         "15f4j4w5q603i7mlphb5r6mb1mn33pqg81595fpjp158140yqx7b"))))
+         "1wybggjzz8zw7aav4pjsg2h22xp17a1lghrprza1pxwlm7wf96y2"))))
     (build-system python-build-system)
     (arguments
      `(#:python ,python-2)) ; only Python 2.7 is supported
     (propagated-inputs
      `(("python2-numpy" ,python2-numpy)
        ("python2-scipy" ,python2-scipy)
-       ("python2-pandas" ,python2-pandas)
+       ("python2-pytz" ,python2-pytz)
        ("python2-cython" ,python2-cython)))
+    (inputs
+     `(("python2-dateutil-2" ,python2-dateutil-2)
+       ("python2-pandas" ,python2-pandas)
+       ("python2-six" ,python2-six)))
     (native-inputs
      `(("unzip" ,unzip)
        ("python2-setuptools" ,python2-setuptools)))
@@ -4253,7 +4257,7 @@ without using the configuration machinery.")
     (source
      (origin
        (method url-fetch)
-       (patches (list (search-patch "python-ipython-inputhook-ctype.patch")))
+       (patches (search-patches "python-ipython-inputhook-ctype.patch"))
        (uri (string-append "https://pypi.python.org/packages/source/i/"
                            "ipython/ipython-" version ".tar.gz"))
        (sha256
@@ -4742,22 +4746,18 @@ Python style, together with a fast and comfortable execution environment.")
 (define-public python-seaborn
   (package
     (name "python-seaborn")
-    (version "0.5.1")
+    (version "0.7.0")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/s/seaborn/seaborn-"
-             version ".tar.gz"))
+       (uri (pypi-uri "seaborn" version))
        (sha256
-        (base32 "1236abw18ijjglmv60q85ckqrvgf5qyy4zlq7nz5aqfg6q87z3wc"))))
+        (base32 "0ibi3xsfm2kysph61mnfy0pf8d5rkgxgrdb0z9nbizgcgdsb5a0m"))))
     (build-system python-build-system)
     (propagated-inputs
      `(("python-pandas" ,python-pandas)
        ("python-matplotlib" ,python-matplotlib)
        ("python-scipy" ,python-scipy)))
-    (native-inputs
-     `(("python-setuptools" ,python-setuptools)))
     (home-page "http://stanford.edu/~mwaskom/software/seaborn/")
     (synopsis "Statistical data visualization")
     (description
@@ -4765,16 +4765,17 @@ Python style, together with a fast and comfortable execution environment.")
 graphics in Python.  It is built on top of matplotlib and tightly integrated
 with the PyData stack, including support for numpy and pandas data structures
 and statistical routines from scipy and statsmodels.")
-    (license bsd-3)))
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-seaborn))))))
 
 (define-public python2-seaborn
-  (let ((seaborn (package-with-python2 python-seaborn)))
-    (package (inherit seaborn)
-      (propagated-inputs
-       `(("python2-pytz" ,python2-pytz)
-         ("python2-pandas" ,python2-pandas)
-         ("python2-matplotlib" ,python2-matplotlib)
-         ("python2-scipy" ,python2-scipy))))))
+  (let ((base (package-with-python2 (strip-python2-variant python-seaborn))))
+    (package
+      (inherit base)
+      (propagated-inputs `(("python2-pytz" ,python2-pytz)
+                           ,@(package-propagated-inputs base)))
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs base))))))
 
 (define-public python-sympy
   (package
@@ -4870,16 +4871,14 @@ It is written entirely in Python.")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/s/singledispatch/"
-             "singledispatch-" version ".tar.gz"))
+       (uri (pypi-uri "singledispatch" version))
        (sha256
         (base32
          "171b7ip0hsq5qm83np40h3phlr36ym18w0lay0a8v08kvy3sy1jv"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
-    (propagated-inputs
+    (inputs
      `(("python-six" ,python-six)))
     (home-page
      "http://docs.python.org/3/library/functools.html#functools.singledispatch")
@@ -4903,11 +4902,10 @@ It is written entirely in Python.")
        (sha256
         (base32 "1gzgwayl6hmc9jfcl88bni4jcsk2jcca9dn1rvrfsvnijcjx7hn9"))))
     (build-system python-build-system)
-    (inputs
-     `(("python-certifi" ,python-certifi)))
     (native-inputs
-     `(("python-backports-abc" ,python-backports-abc)
-       ("python-setuptools" ,python-setuptools)))
+     `(("python-certifi" ,python-certifi)))
+    (inputs
+     `(("python-backports-abc" ,python-backports-abc)))
     (home-page "http://www.tornadoweb.org/")
     (synopsis "Python web framework and asynchronous networking library")
     (description
@@ -4916,16 +4914,20 @@ originally developed at FriendFeed.  By using non-blocking network I/O,
 Tornado can scale to tens of thousands of open connections, making it ideal
 for long polling, WebSockets, and other applications that require a long-lived
 connection to each user.")
-    (license asl2.0)))
+    (license asl2.0)
+    (properties `((python2-variant . ,(delay python2-tornado))))))
 
 (define-public python2-tornado
-  (let ((tornado (package-with-python2 python-tornado)))
+  (let ((tornado (package-with-python2 (strip-python2-variant python-tornado))))
     (package (inherit tornado)
       (inputs
        `(("python2-backport-ssl-match-hostname"
           ,python2-backport-ssl-match-hostname)
-         ("python2-singledispatch", python2-singledispatch)
-         ,@(package-inputs tornado))))))
+         ("python2-singledispatch" ,python2-singledispatch)
+          ,@(package-inputs tornado)))
+      (native-inputs
+       `(("python2-setuptools" ,python2-setuptools)
+         ,@(package-native-inputs tornado))))))
 
 ;; the python- version can be removed with python-3.5
 (define-public python-backports-abc
@@ -5296,23 +5298,20 @@ pseudo terminal (pty), and interact with both the process and its pty.")
 (define-public python-terminado
   (package
     (name "python-terminado")
-    (version "0.5")
+    (version "0.6")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/t/terminado/terminado-"
-             version ".tar.gz"))
+       (uri (pypi-uri "terminado" version))
        (sha256
         (base32
-         "1dkmp1n8dj5v1jl9mfrq8lwyc7dsfrvcmz2bgkpg315sy7pr7s33"))))
+         "09h1kwi86g5mrk14s4pgbhshd602zry29lnpxamcqz864kva22rc"))))
     (build-system python-build-system)
     (propagated-inputs
      `(("python-tornado" ,python-tornado)
        ("python-ptyprocess" ,python-ptyprocess)))
-    (inputs
-     `(("python-setuptools" ,python-setuptools)
-       ("python-nose" ,python-nose)))
+    (native-inputs
+     `(("python-nose" ,python-nose)))
     (arguments
      `(#:phases
        (modify-phases %standard-phases
@@ -5323,17 +5322,19 @@ pseudo terminal (pty), and interact with both the process and its pty.")
     (synopsis "Terminals served to term.js using Tornado websockets")
     (description "This package provides a Tornado websocket backend for the
 term.js Javascript terminal emulator library.")
-    (license bsd-2)))
+    (license bsd-2)
+    (properties `((python2-variant . ,(delay python2-terminado))))))
 
 (define-public python2-terminado
-  (let ((terminado (package-with-python2 python-terminado)))
+  (let ((terminado (package-with-python2 (strip-python2-variant python-terminado))))
     (package (inherit terminado)
-             (propagated-inputs
-              `(("python2-tornado" ,python2-tornado)
-                ("python2-backport-ssl-match-hostname"
-                 ,python2-backport-ssl-match-hostname)
-                ,@(alist-delete "python-tornado"
-                                (package-propagated-inputs terminado)))))))
+      (propagated-inputs
+       `(("python2-backport-ssl-match-hostname"
+          ,python2-backport-ssl-match-hostname)
+          ,@(package-propagated-inputs terminado)))
+      (native-inputs
+       `(("python2-setuptools" ,python2-setuptools)
+         ,@(package-native-inputs terminado))))))
 
 (define-public python-fonttools
   (package
@@ -5369,16 +5370,16 @@ from an XML-based format.")
 (define-public python-ly
   (package
     (name "python-ly")
-    (version "0.9.3")
+    (version "0.9.4")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/p/python-ly/python-ly-"
-             version ".tar.gz"))
+       (uri (string-append "https://pypi.python.org/packages/57/4f/"
+                           "889579244947368f28eda66b782331b1e75f83fd72e63f9ece93cd7a18f9"
+                           "/python-ly-" version ".tar.gz"))
        (sha256
         (base32
-         "1y6ananq8fia4y4m5id6gvsrm68bzpzd1y46pfzvawic0wjg2l0l"))))
+         "0g6n288l83sfwavxh1aryi0aqvsr3sp7v6f903mckwqa4scpky62"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
@@ -6586,16 +6587,14 @@ timestamps.")
 (define-public python-werkzeug
   (package
     (name "python-werkzeug")
-    (version "0.11.2")
+    (version "0.11.5")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "https://pypi.python.org/packages/source/W/Werkzeug"
-                           "/Werkzeug-" version ".tar.gz"))
-       (file-name (string-append name "-" version ".tar.gz"))
+       (uri (pypi-uri "Werkzeug" version))
        (sha256
         (base32
-         "1gzwn1lkl90f3l1nzzxr7vjhm21qk8f837i8rvny5a209fcrhkzb"))))
+         "0r41xqp4cypzcgsf6zbspbqd272wnzf20igb4w4b5wzfhgqh9nxg"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-pytest" ,python-pytest)))
@@ -6625,7 +6624,7 @@ addon modules.")
                 "00h9rcmws03xvdlfni11yb60bz3kxfvsj6dg6nrpzj71f03nbxd2"))
               ;; Patch setup.py so it looks for python-setuptools, which is
               ;; required to parse the keyword 'install_requires' in setup.py.
-              (patches (list (search-patch "python-configobj-setuptools.patch")))))
+              (patches (search-patches "python-configobj-setuptools.patch"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)
@@ -6871,7 +6870,7 @@ applications.")
               (base32
                "1iks5701qnp3dlr3q1d9qm68y2plp2m029irhpz92a44psfkjf1f"))))
     (build-system python-build-system)
-    (propagated-inputs
+    (inputs
      `(("python-pytest" ,python-pytest)))
     (synopsis "Namespace control and lazy-import mechanism")
     (description "With apipkg you can control the exported namespace of a Python
@@ -6901,7 +6900,7 @@ pure Python module that works on virtually all Python versions.")
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools-scm" ,python-setuptools-scm)))
-    (propagated-inputs
+    (inputs
      `(("python-apipkg" ,python-apipkg)))
     (synopsis "Rapid multi-Python deployment")
     (description "Execnet provides a share-nothing model with
@@ -6938,8 +6937,11 @@ minimal and fast API targetting the following uses:
               (base32
                "1a873fihw4rhshc722j4h6j7g3nj7xpgsna9hhg3zn6ksknnhx5y"))))
     (build-system python-build-system)
-    (propagated-inputs
-     `(("python-execnet" ,python-execnet)))
+    (inputs
+     `(("python-apipkg" ,python-apipkg)
+       ("python-execnet" ,python-execnet)
+       ("python-py" ,python-py)
+       ("python-pytest" ,python-pytest)))
     (synopsis "Py.test plugin with mechanisms for caching across test runs")
     (description "The pytest-cache plugin provides tools to rerun failures from
 the last py.test invocation.")
@@ -6964,12 +6966,11 @@ the last py.test invocation.")
              (zero? (system* "py.test" "--genscript=runtests.py"))
              (zero? (system* "py.test")))))))
     (native-inputs
-     `(("unzip" ,unzip)))
-    (propagated-inputs
      `(("python-pytest" ,python-pytest)
        ("python-requests" ,python-requests)
-       ("python-six" ,python-six)
-       ("python-werkzeug" ,python-werkzeug)))
+       ("python-six" ,python-six)))
+    (inputs
+     `(("python-werkzeug" ,python-werkzeug)))
     (synopsis "Py.test plugin to test server connections locally")
     (description "Pytest-localserver is a plugin for the pytest testing
 framework which enables you to test server connections locally.")
@@ -7201,9 +7202,7 @@ Python at your fingertips, in Lisp form.")
     (build-system python-build-system)
     (arguments
      `(#:test-target "check"))
-    (native-inputs
-     `(("python-setuptools" ,python-setuptools)))
-    (propagated-inputs
+    (inputs
      `(("python-requests" ,python-requests)))
     (home-page "https://github.com/litl/rauth")
     (synopsis "Python library for OAuth 1.0/a, 2.0, and Ofly")
@@ -7211,15 +7210,16 @@ Python at your fingertips, in Lisp form.")
      "Rauth is a Python library for OAuth 1.0/a, 2.0, and Ofly.  It also
 provides service wrappers for convenient connection initialization and
 authenticated session objects providing things like keep-alive.")
-    (license license:expat)))
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-rauth))))))
 
 (define-public python2-rauth
-  (let ((rauth (package-with-python2 python-rauth)))
-    (package (inherit rauth)
-      (propagated-inputs `(("python2-requests" ,python2-requests)))
-      (native-inputs
-       `(("python2-unittest2" ,python2-unittest2)
-         ,@(package-native-inputs rauth))))))
+  (let ((base (package-with-python2 (strip-python2-variant python-rauth))))
+    (package
+      (inherit base)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ("python2-unittest2" ,python2-unittest2)
+                       ,@(package-native-inputs base))))))
 
 (define-public python2-functools32
   (package
@@ -7748,10 +7748,8 @@ file.")
        (sha256
         (base32
          "16dsv9qi0r4qsrsb6dilpq2rx0fnglvh36flzywcdnm2jg43mb5d"))
-       (patches (list (search-patch
-                       "python-paste-remove-website-test.patch")
-                      (search-patch
-                       "python-paste-remove-timing-test.patch")))))
+       (patches (search-patches "python-paste-remove-website-test.patch"
+                                "python-paste-remove-timing-test.patch"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-nose" ,python-nose)))
@@ -8070,8 +8068,10 @@ Python 2.4 and 2.5, and will draw its fixes/improvements from python-trunk.")
     (build-system python-build-system)
     (native-inputs
      `(("python-nose" ,python-nose)))
-    (propagated-inputs
+    (inputs
      `(("python-pytz" ,python-pytz)
+       ("python-amqp" ,python-amqp)
+       ("python-anyjson" ,python-anyjson)
        ("python-billiard" ,python-billiard)
        ("python-kombu" ,python-kombu)))
     (home-page "http://celeryproject.org")
@@ -8240,13 +8240,13 @@ introspection of @code{zope.interface} instances in code.")
 (define-public python-vobject
   (package
     (name "python-vobject")
-    (version "0.9.1")
+    (version "0.9.2")
     (source (origin
               (method url-fetch)
               (uri (pypi-uri "vobject" version))
               (sha256
                (base32
-                "1cwzjnrdr9yg2x21wbf3kf59ibnchvj33mygd69yzi178a9gs9gz"))))
+                "1qfnwlx8qwkgr6nf5wvl6ff1r3kll53dh3z6nyp173nmlhhhqccb"))))
     (build-system python-build-system)
     (inputs
      `(("python-dateutil-2" ,python-dateutil-2)
@@ -8483,7 +8483,7 @@ module, adding support for Unicode strings.")
                (base32
                 "0d8n1dlpiz7av8dmbp0vclrwl9cnxizr4f2c9xvj1h5nvn480527"))
               ;; https://github.com/markokr/rarfile/pull/17/
-              (patches (list (search-patch "python-rarfile-fix-tests.patch")))))
+              (patches (search-patches "python-rarfile-fix-tests.patch"))))
     (build-system python-build-system)
     (arguments
      '(#:phases
@@ -8603,3 +8603,133 @@ Service (S3) protocol, including S3 itself.  It supports rsync-like backup,
 GnuPG encryption, and more.  It also supports management of Amazon's
 CloudFront content delivery network.")
     (license gpl2+)))
+
+(define-public python-pkgconfig
+  (package
+    (name "python-pkgconfig")
+    (version "1.1.0")
+    (source
+      (origin
+        (method url-fetch)
+        (uri (pypi-uri "pkgconfig" version))
+        (sha256
+          (base32
+            "1pw0kmvc57sjmaxi6c54fqsnihqj6hvhc9y1vaz36axafzqam7bh"))))
+    (build-system python-build-system)
+    (native-inputs
+      `(("python-nose" ,python-nose)
+        ("python-setuptools" ,python-setuptools)))
+    (inputs
+      `(("pkg-config" ,pkg-config)))
+    (arguments
+      `(;; Tests fail with "ValueError: _type_ 'v' not supported" on Python 3,
+        ;; and on Python 2 they need the dl module deprecated since Python 2.6.
+        #:tests? #f
+        ;; Prevent creation of the egg. This works around
+        ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=20765 .
+        #:configure-flags '("--single-version-externally-managed" "--root=/")
+        ;; Hard-code the path to pkg-config.
+        #:phases
+        (modify-phases %standard-phases
+          (add-before
+           'build 'patch
+           (lambda _
+             (substitute* "pkgconfig/pkgconfig.py"
+               (("cmd = 'pkg-config")
+                (string-append "cmd = '" (which "pkg-config"))))
+             #t)))))
+    (home-page "http://github.com/matze/pkgconfig")
+    (synopsis "Python interface for pkg-config")
+    (description "This module provides a Python interface to pkg-config.  It
+can be used to find all pkg-config packages, check if a package exists,
+check if a package meets certain version requirements, query CFLAGS and
+LDFLAGS and parse the output to build extensions with setup.py.")
+    (license license:expat)))
+
+(define-public python2-pkgconfig
+  (package-with-python2 python-pkgconfig))
+
+(define-public python-cysignals
+  (package
+    (name "python-cysignals")
+    (version "1.1.0")
+    (source
+      (origin
+        (method url-fetch)
+        (uri (pypi-uri "cysignals" version ".tar.bz2"))
+        (sha256
+          (base32
+            "14cbyd9znlz6cxy1s3g6v6dv5jj45hn27pywkidd9b1zanaysqc6"))))
+    (build-system python-build-system)
+    (native-inputs
+      `(("python-cython" ,python-cython)
+        ("python-setuptools" ,python-setuptools)
+        ("python-sphinx" ,python-sphinx)))
+    (inputs
+      `(("pari-gp" ,pari-gp)))
+    (arguments
+     `(#:modules ((guix build python-build-system)
+                  ((guix build gnu-build-system) #:prefix gnu:)
+                  (guix build utils))
+       ;; FIXME: Tests are executed after installation and currently fail
+       ;; when not installing into standard locations; the author is working
+       ;; on a fix.
+       #:tests? #f
+       #:phases
+       (modify-phases %standard-phases
+         (add-before
+          'build 'configure
+          (assoc-ref gnu:%standard-phases 'configure)))))
+    (home-page
+      "https://github.com/sagemath/cysignals")
+    (synopsis
+      "Handling of interrupts and signals for Cython")
+    (description
+      "The cysignals package provides mechanisms to handle interrupts (and
+other signals and errors) in Cython code, using two related approaches,
+for mixed Cython/Python code or external C libraries and pure Cython code,
+respectively.")
+    (license lgpl3+)))
+
+(define-public python2-cysignals
+  (package-with-python2 python-cysignals))
+
+(define-public python2-shedskin
+ (package
+  (name "python2-shedskin")
+  (version "0.9.4")
+  (source
+    (origin
+      (method url-fetch)
+      (uri (string-append "https://github.com/shedskin/shedskin/"
+                          "releases/download/v" version
+                          "/shedskin-" version ".tgz"))
+      (sha256
+        (base32
+          "0nzwrzgw1ga8rw6f0ryq7zr9kkiavd1cqz5hzxkcbicl1dk7kz41"))))
+  (build-system python-build-system)
+  (arguments
+   `(#:python ,python-2
+     #:phases (modify-phases %standard-phases
+               (add-after 'unpack 'fix-resulting-include-libs
+                (lambda* (#:key inputs #:allow-other-keys)
+                 (let ((libgc (assoc-ref inputs "libgc"))
+                       (pcre (assoc-ref inputs "pcre")))
+                  (substitute* "shedskin/makefile.py"
+                   (("variable == 'CCFLAGS':[ ]*")
+                    (string-append "variable == 'CCFLAGS':\n"
+                                   "            line += ' -I " pcre "/include"
+                                   " -I " libgc "/include'"))
+                   (("variable == 'LFLAGS':[ ]*")
+                    (string-append "variable == 'LFLAGS':\n"
+                                   "            line += ' -L" pcre "/lib"
+                                   " -L " libgc "/lib'")))
+                  #t))))))
+  (native-inputs `(("python2-setuptools" ,python2-setuptools)))
+  (inputs `(("pcre" ,pcre)
+            ("libgc" ,libgc)))
+  (home-page "https://shedskin.github.io/")
+  (synopsis "Experimental Python-2 to C++ Compiler")
+  (description (string-append "This is an experimental compiler for a subset of
+Python.  It generates C++ code and a Makefile."))
+  (license (list gpl3 bsd-3 license:expat))))
diff --git a/gnu/packages/qemu.scm b/gnu/packages/qemu.scm
index 1104a2da6a..c0ee504b24 100644
--- a/gnu/packages/qemu.scm
+++ b/gnu/packages/qemu.scm
@@ -62,20 +62,19 @@
              (sha256
               (base32
                "1m3j6xl7msrniidkvr5pw9d44yba5m7hm42xz8xy77v105s8hhrl"))
-             (patches
-              (map search-patch
-                   '("qemu-virtio-9p-use-accessor-to-get-thread-pool.patch"
-                     "qemu-CVE-2015-8558.patch"
-                     "qemu-CVE-2015-8567.patch"
-                     "qemu-CVE-2016-1922.patch"
-                     "qemu-CVE-2015-8613.patch"
-                     "qemu-CVE-2015-8701.patch"
-                     "qemu-CVE-2015-8743.patch"
-                     "qemu-CVE-2016-1568.patch"
-                     "qemu-CVE-2015-8619.patch"
-                     "qemu-CVE-2016-1981.patch"
-                     "qemu-usb-ehci-oob-read.patch"
-                     "qemu-CVE-2016-2197.patch")))))
+             (patches (search-patches
+                       "qemu-virtio-9p-use-accessor-to-get-thread-pool.patch"
+                       "qemu-CVE-2015-8558.patch"
+                       "qemu-CVE-2015-8567.patch"
+                       "qemu-CVE-2016-1922.patch"
+                       "qemu-CVE-2015-8613.patch"
+                       "qemu-CVE-2015-8701.patch"
+                       "qemu-CVE-2015-8743.patch"
+                       "qemu-CVE-2016-1568.patch"
+                       "qemu-CVE-2015-8619.patch"
+                       "qemu-CVE-2016-1981.patch"
+                       "qemu-usb-ehci-oob-read.patch"
+                       "qemu-CVE-2016-2197.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-replace
diff --git a/gnu/packages/qt.scm b/gnu/packages/qt.scm
index bfd99b6519..7b2be4f4e9 100644
--- a/gnu/packages/qt.scm
+++ b/gnu/packages/qt.scm
@@ -252,8 +252,7 @@ developers using C++ or QML, a CSS & JavaScript like language.")
              (sha256
               (base32
                "183fca7n7439nlhxyg1z7aky0izgbyll3iwakw4gwivy16aj5272"))
-             (patches (map search-patch
-                           '("qt4-ldflags.patch")))
+             (patches (search-patches "qt4-ldflags.patch"))
              (modules '((guix build utils)))
              (snippet
               ;; Remove webkit module, which is not built.
@@ -440,7 +439,7 @@ module provides support functions to the automatically generated code.")
         (sha256
          (base32
           "056qmkv02wdcfblqdaxiswrgn4wa88sz22i1x58dpb1iniavplfd"))
-       (patches (list (search-patch "pyqt-configure.patch")))))
+       (patches (search-patches "pyqt-configure.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("python-sip" ,python-sip)
diff --git a/gnu/packages/ratpoison.scm b/gnu/packages/ratpoison.scm
index dc6db7258f..23adf859a7 100644
--- a/gnu/packages/ratpoison.scm
+++ b/gnu/packages/ratpoison.scm
@@ -51,7 +51,7 @@
              (sha256
               (base32
                "1w502z55vv7zs45l80nsllqh9fvfwjfdfi11xy1qikhzdmirains"))
-             (patches (list (search-patch "ratpoison-shell.patch")))))
+             (patches (search-patches "ratpoison-shell.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases
diff --git a/gnu/packages/rdf.scm b/gnu/packages/rdf.scm
index b577e266f9..958716a447 100644
--- a/gnu/packages/rdf.scm
+++ b/gnu/packages/rdf.scm
@@ -89,9 +89,8 @@ HTML and JSON.")
              (sha256
               (base32
                "1arffdwivig88kkx685pldr784njm0249k0rb1f1plwavlrw9zfx"))
-             (patches (list
-                       (search-patch "clucene-pkgconfig.patch")
-                       (search-patch "clucene-contribs-lib.patch")))))
+             (patches (search-patches "clucene-pkgconfig.patch"
+                                      "clucene-contribs-lib.patch"))))
     (build-system cmake-build-system)
     (inputs
      `(("boost" ,boost) ; could also use bundled copy
@@ -311,7 +310,7 @@ ideal (e.g. in LV2 implementations or embedded applications).")
               ".tar.gz"))
         (patches
           ;; The patch has no effect under Python 3.
-          (list (search-patch "python2-rdflib-drop-sparqlwrapper.patch")))
+          (search-patches "python2-rdflib-drop-sparqlwrapper.patch"))
         (sha256
           (base32
             "0kvaf332cqbi47rqzlpdx4mbkvw12mkrzkj8n9l19wk713d4py9w"))))
diff --git a/gnu/packages/readline.scm b/gnu/packages/readline.scm
index 13ce9165f4..db469db051 100644
--- a/gnu/packages/readline.scm
+++ b/gnu/packages/readline.scm
@@ -46,7 +46,7 @@
                (sha256
                 (base32
                  "0hzxr9jxqqx5sxsv9vmlxdnvlr9vi4ih1avjb869hbs6p5qn1fjn"))
-               (patches (list (search-patch "readline-link-ncurses.patch")))
+               (patches (search-patches "readline-link-ncurses.patch"))
                (patch-flags '("-p0"))))
       (build-system gnu-build-system)
       (propagated-inputs `(("ncurses" ,ncurses)))
diff --git a/gnu/packages/ruby.scm b/gnu/packages/ruby.scm
index 0ca3415a9f..6c2e08f29d 100644
--- a/gnu/packages/ruby.scm
+++ b/gnu/packages/ruby.scm
@@ -46,7 +46,7 @@
 (define-public ruby
   (package
     (name "ruby")
-    (version "2.3.0")
+    (version "2.3.1")
     (source
      (origin
        (method url-fetch)
@@ -55,8 +55,9 @@
                            "/ruby-" version ".tar.xz"))
        (sha256
         (base32
-         "15s0dsb5ynf3d2w5gzawnszq5594fqvapv2y7a0qw16przq5l4kh"))
+         "0f3395q7pd2hrl2gv26bib80038sjawxgmhl9zn22fjs9m9va9b7"))
        (modules '((guix build utils)))
+       (patches (search-patches "ruby-symlinkfix.patch"))
        (snippet `(begin
                    ;; Remove bundled libffi
                    (delete-file-recursively
@@ -102,7 +103,7 @@ a focus on simplicity and productivity.")
 
 (define-public ruby-2.2
   (package (inherit ruby)
-    (version "2.2.4")
+    (version "2.2.5")
     (source
      (origin
        (method url-fetch)
@@ -111,13 +112,7 @@ a focus on simplicity and productivity.")
                            "/ruby-" version ".tar.xz"))
        (sha256
         (base32
-         "0g3ps4q3iz7wj9m45n8xyxzw8nh29ljdqb87b0f6i0p3853gz2yj"))
-       (modules '((guix build utils)))
-       (snippet `(begin
-                   ;; Remove bundled libffi
-                   (delete-file-recursively
-                    (string-append "ext/fiddle/libffi-3.2.1"))
-                   #t))))))
+         "1mw7bzw76g5w37cwhb57r6gxcl2vn9lfrlyf4h4xms3qlnhflvzq"))))))
 
 (define-public ruby-2.1
   (package (inherit ruby)
@@ -3528,14 +3523,14 @@ subprocess.")
 (define-public ruby-bio-commandeer
   (package
     (name "ruby-bio-commandeer")
-    (version "0.1.2")
+    (version "0.1.3")
     (source
      (origin
        (method url-fetch)
        (uri (rubygems-uri "bio-commandeer" version))
        (sha256
         (base32
-         "061jxa6km92qfwzl058r2gp8gfcsbyr7m643nw1pxvmjdswaf6ly"))))
+         "0lin6l99ldqqjc90l9ihcrv882c4xgbgqm16jqkdy6jf955jd9a8"))))
     (build-system ruby-build-system)
     (arguments
      `(#:phases
@@ -3742,14 +3737,14 @@ Rubytest-based test frameworks.  It provides the @code{rubytest} executable.")
 (define-public ruby-hashery
   (package
     (name "ruby-hashery")
-    (version "2.1.1")
+    (version "2.1.2")
     (source
      (origin
        (method url-fetch)
        (uri (rubygems-uri "hashery" version))
        (sha256
         (base32
-         "0xawbljsjarl9l7700bka672ixwznzwih4s9i38p1y9mp8hyx54g"))))
+         "0qj8815bf7q6q7llm5rzdz279gzmpqmqqicxnzv066a020iwqffj"))))
     (build-system ruby-build-system)
     (arguments
      `(#:phases
diff --git a/gnu/packages/rush.scm b/gnu/packages/rush.scm
index 0a65599e24..6926f68787 100644
--- a/gnu/packages/rush.scm
+++ b/gnu/packages/rush.scm
@@ -36,7 +36,7 @@
              (sha256
               (base32
                "0fh0gbbp0iiq3wbkf503xb40r8ljk42vyj9bnlflbz82d6ipy1rm"))
-             (patches (list (search-patch "cpio-gets-undeclared.patch")))))
+             (patches (search-patches "cpio-gets-undeclared.patch"))))
     (build-system gnu-build-system)
     (home-page "http://www.gnu.org/software/rush/")
     (synopsis "Restricted user (login) shell")
diff --git a/gnu/packages/samba.scm b/gnu/packages/samba.scm
index 8c4f064cf8..8aac6a5dc1 100644
--- a/gnu/packages/samba.scm
+++ b/gnu/packages/samba.scm
@@ -99,14 +99,14 @@ anywhere.")
 (define-public samba
   (package
     (name "samba")
-    (version "4.3.6")
+    (version "4.3.8")
     (source (origin
              (method url-fetch)
              (uri (string-append "https://www.samba.org/samba/ftp/stable/samba-"
                                  version ".tar.gz"))
              (sha256
               (base32
-               "0929fpk2pq4v389naai519xvsm9bzpar4jlgjxwlx1cnn6jyql9j"))))
+               "041b5frh4ikcka922aqhqjvlv4w2s7jycyykpvsknj0a79ncd79p"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases
diff --git a/gnu/packages/scheme.scm b/gnu/packages/scheme.scm
index 50533b9a29..6cf75c2471 100644
--- a/gnu/packages/scheme.scm
+++ b/gnu/packages/scheme.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
 ;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>
 ;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
@@ -174,7 +174,8 @@
      "GNU/MIT Scheme is an implementation of the Scheme programming
 language.  It provides an interpreter, a compiler and a debugger.  It also
 features an integrated Emacs-like editor and a large runtime library.")
-    (license gpl2+)))
+    (license gpl2+)
+    (properties '((ftp-directory . "/gnu/mit-scheme/stable.pkg")))))
 
 (define-public bigloo
   (package
@@ -187,7 +188,7 @@ features an integrated Emacs-like editor and a large runtime library.")
              (sha256
               (base32
                "170q7nh08n4v20xl81fxb0xcdxphqqacfa643hsa8i2ar6pki04c"))
-             (patches (list (search-patch "bigloo-gc-shebangs.patch")))))
+             (patches (search-patches "bigloo-gc-shebangs.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:test-target "test"
@@ -277,8 +278,8 @@ Scheme and C programs and between Scheme and Java programs.")
              (sha256
               (base32
                "1v2r4ga58kk1sx0frn8qa8ccmjpic9csqzpk499wc95y9c4b1wy3"))
-             (patches (list (search-patch "hop-bigloo-4.0b.patch")
-                            (search-patch "hop-linker-flags.patch")))))
+             (patches (search-patches "hop-bigloo-4.0b.patch"
+                                      "hop-linker-flags.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:phases
@@ -374,7 +375,7 @@ language standard, and includes many enhancements and extensions.")
              (sha256
               (base32
                "1x4xfm3lyz2piqcw1h01vbs1iq89zq7wrsfjgh3fxnlm1slj2jcw"))
-             (patches (list (search-patch "scheme48-tests.patch")))))
+             (patches (search-patches "scheme48-tests.patch"))))
     (build-system gnu-build-system)
     (home-page "http://s48.org/")
     (synopsis "Scheme implementation using a bytecode interpreter")
diff --git a/gnu/packages/screen.scm b/gnu/packages/screen.scm
index 088ca559d8..4b9bacf3e5 100644
--- a/gnu/packages/screen.scm
+++ b/gnu/packages/screen.scm
@@ -107,7 +107,7 @@ controlling terminal and attach to it later.")
        (sha256
         (base32
          "1s8nh4wbds1nh52i0d1hy1b308jjf4siwpq92lna1zh9ll4x71j5"))
-       (patches (list (search-patch "byobu-writable-status.patch")))))
+       (patches (search-patches "byobu-writable-status.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("python" ,python-wrapper)       ;for config and session GUIs
diff --git a/gnu/packages/sdl.scm b/gnu/packages/sdl.scm
index 458fdc599f..49b9deaf4d 100644
--- a/gnu/packages/sdl.scm
+++ b/gnu/packages/sdl.scm
@@ -60,7 +60,7 @@
              (sha256
               (base32
                "005d993xcac8236fpvd1iawkz4wqjybkpn8dbwaliqz5jfkidlyn"))
-             (patches (list (search-patch "sdl-libx11-1.6.patch")))))
+             (patches (search-patches "sdl-libx11-1.6.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(;; Explicitly link against shared libraries instead of dlopening them.
diff --git a/gnu/packages/slim.scm b/gnu/packages/slim.scm
index 8e25a5a669..dfb37a94bc 100644
--- a/gnu/packages/slim.scm
+++ b/gnu/packages/slim.scm
@@ -44,9 +44,9 @@
                    version ".tar.gz"))
 	     (sha256
 	      (base32 "1pqhk22jb4aja4hkrm7rjgbgzjyh7i4zswdgf5nw862l2znzxpi1"))
-             (patches (map search-patch
-                           (list "slim-config.patch" "slim-session.patch"
-                                 "slim-sigusr1.patch")))))
+             (patches (search-patches "slim-config.patch"
+                                      "slim-session.patch"
+                                      "slim-sigusr1.patch"))))
     (build-system cmake-build-system)
     (inputs `(("linux-pam" ,linux-pam)
 	      ("libpng" ,libpng)
diff --git a/gnu/packages/ssh.scm b/gnu/packages/ssh.scm
index d7f2f363a8..b8f107b111 100644
--- a/gnu/packages/ssh.scm
+++ b/gnu/packages/ssh.scm
@@ -82,8 +82,8 @@ remote applications.")
               (sha256
                (base32
                 "0b6wyx6bwbb8jpn8x4rhlrdiqwqrwrs0mxjmrnqykm9kw1ijgm8g"))
-              (patches (list
-                        (search-patch "libssh-0.6.5-CVE-2016-0739.patch")))))))
+              (patches (search-patches
+                        "libssh-0.6.5-CVE-2016-0739.patch"))))))
 
 (define-public libssh2
   (package
@@ -126,7 +126,8 @@ a server that supports the SSH-2 protocol.")
                          (string-append "http://ftp2.fr.openbsd.org/pub/OpenBSD/OpenSSH/portable/"
                                         tail))))
             (sha256 (base32
-                     "132lh9aanb0wkisji1d6cmsxi520m8nh7c7i9wi6m1s3l38q29x7"))))
+                     "132lh9aanb0wkisji1d6cmsxi520m8nh7c7i9wi6m1s3l38q29x7"))
+            (patches (search-patches "openssh-CVE-2015-8325.patch"))))
    (build-system gnu-build-system)
    (inputs `(("groff" ,groff)
              ("openssl" ,openssl)
diff --git a/gnu/packages/statistics.scm b/gnu/packages/statistics.scm
index 9c197f4977..3d0faf7572 100644
--- a/gnu/packages/statistics.scm
+++ b/gnu/packages/statistics.scm
@@ -40,6 +40,7 @@
   #:use-module (gnu packages image)
   #:use-module (gnu packages java)
   #:use-module (gnu packages maths)
+  #:use-module (gnu packages multiprecision)
   #:use-module (gnu packages pcre)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages pkg-config)
@@ -97,7 +98,7 @@ be output in text, PostScript, PDF or HTML.")
 (define-public r
   (package
     (name "r")
-    (version "3.2.3")
+    (version "3.2.5")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://cran/src/base/R-"
@@ -105,7 +106,7 @@ be output in text, PostScript, PDF or HTML.")
                                   version ".tar.gz"))
               (sha256
                (base32
-                "1hdnv77ralzcx5k5b88jq1r8l6zqnywpq00g2qs949rqh63psfxr"))))
+                "1dc0iybjk9kr1nghz3fpir6mb9hb9rnrz9bgh00w5pg5vir5cx30"))))
     (build-system gnu-build-system)
     (arguments
      `(#:make-flags
@@ -224,14 +225,19 @@ effects of different types of color-blindness.")
 (define-public r-digest
   (package
     (name "r-digest")
-    (version "0.6.8")
+    (version "0.6.9")
     (source
      (origin
        (method url-fetch)
        (uri (cran-uri "digest" version))
        (sha256
-        (base32 "0m9grqv67hhf51lz10whymhw0g0d98466ka694kya5x95hn44qih"))))
+        (base32 "0ixy1mb7kfl20lkckqiilpw03g1ip4ibihs03gicz7w625hc7zcm"))))
     (build-system r-build-system)
+    ;; Vignettes require r-knitr, which requires r-digest, so we have to
+    ;; disable them and the tests.
+    (arguments
+     `(#:tests? #f
+       #:configure-flags (list "--no-build-vignettes")))
     (home-page "http://dirk.eddelbuettel.com/code/digest.html")
     (synopsis "Create cryptographic hash digests of R objects")
     (description
@@ -305,13 +311,13 @@ see package vignette.  To quote Rene Magritte, \"Ceci n'est pas un pipe.\"")
 (define-public r-munsell
   (package
     (name "r-munsell")
-    (version "0.4.2")
+    (version "0.4.3")
     (source
      (origin
        (method url-fetch)
        (uri (cran-uri "munsell" version))
        (sha256
-        (base32 "1bi5yi0i80778bbzx2rm4f0glpc34kvh24pwwfhm4v32izsqgrw4"))))
+        (base32 "0jdxlbjslkzaqgp058da1cgm85qvqi09wpcgpvp4hvwnmy83qz1r"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-colorspace" ,r-colorspace)))
@@ -325,13 +331,13 @@ Munsell colour system.")
 (define-public r-rcpp
   (package
     (name "r-rcpp")
-    (version "0.12.0")
+    (version "0.12.4")
     (source
      (origin
        (method url-fetch)
        (uri (cran-uri "Rcpp" version))
        (sha256
-        (base32 "182109z0yc1snqgd833ssl2cix6cbq83bcxmy5344b15ym820y38"))))
+        (base32 "1lyhyaxrnb5w4igi3l1p378s4jblcnrv6h7h5ym42ljm54mm44w3"))))
     (build-system r-build-system)
     (home-page "http://www.rcpp.org")
     (synopsis "Seamless R and C++ Integration")
@@ -408,14 +414,14 @@ designed by Cynthia Brewer as described at http://colorbrewer2.org")
 (define-public r-stringi
   (package
     (name "r-stringi")
-    (version "0.5-5")
+    (version "1.0-1")
     (source
      (origin
        (method url-fetch)
        (uri (cran-uri "stringi" version))
        (sha256
         (base32
-         "183wrrjhpgl1wbnn9lhghyvhz7l2mc64mpcmzplckal7y9j7pmhw"))))
+         "1ld38536sswyywp6pyys3v8vkngbk5cksrhdxp8jyr6bz7qf8j77"))))
     (build-system r-build-system)
     (inputs `(("icu4c" ,icu4c)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -480,13 +486,13 @@ using just two functions: melt and dcast (or acast).")
 (define-public r-scales
   (package
     (name "r-scales")
-    (version "0.3.0")
+    (version "0.4.0")
     (source
      (origin
        (method url-fetch)
        (uri (cran-uri "scales" version))
        (sha256
-        (base32 "1kkgpqzb0a6lnpblhcprr4qzyfk5lhicdv4639xs5cq16n7bkqgl"))))
+        (base32 "19y6q4j8vpmc73dnn4ncp5wj44gri7m77ys3z2rn3crrcc9zc7l5"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-dichromat" ,r-dichromat)
@@ -506,13 +512,13 @@ legends.")
 (define-public r-ggplot2
   (package
     (name "r-ggplot2")
-    (version "2.0.0")
+    (version "2.1.0")
     (source
      (origin
        (method url-fetch)
        (uri (cran-uri "ggplot2" version))
        (sha256
-        (base32 "07r5zw0ccv4sf1mdxcz9wa86p2c6j61cnnq18qdjrh3zhhcbmdp2"))))
+        (base32 "0s9rvp0f736ji6p9xpxq54agxf95pjkql4sj7ag0hv2xhnp27hzj"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-digest" ,r-digest)
@@ -593,13 +599,13 @@ R/DBMS implementations.")
 (define-public r-bh
   (package
     (name "r-bh")
-    (version "1.58.0-1")
+    (version "1.60.0-1")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "BH" version))
               (sha256
                (base32
-                "17rnwyw9ib2pvm60iixzkbz7ff4fslpifp1nlx4czp42hy67kqpf"))))
+                "08gc3b0irgvpjl59irdxs8jhlbky4yp4fvs3zi4pq0wdwj43cfsk"))))
     (build-system r-build-system)
     (home-page "https://github.com/eddelbuettel/bh")
     (synopsis "R package providing subset of Boost headers")
@@ -611,13 +617,13 @@ for template use among CRAN packages.")
 (define-public r-evaluate
   (package
     (name "r-evaluate")
-    (version "0.8")
+    (version "0.8.3")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "evaluate" version))
               (sha256
                (base32
-                "137gc35jlizhqnx19mxim3llrkm403abj8ghb2b7v5ls9rvd40pq"))))
+                "08d6164m9wqf9qq6yh1s9a0qxwqzqpsq7312hilzy79gxf9gixzr"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-stringr" ,r-stringr)))
@@ -633,13 +639,13 @@ adapted for other output formats, such as HTML or LaTeX.")
 (define-public r-formatr
   (package
     (name "r-formatr")
-    (version "1.2.1")
+    (version "1.3")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "formatR" version))
               (sha256
                (base32
-                "0f4cv2zv5wayyqx99ybfyl0p83kgjvnsv8dhcwa4s49kw6jsx1lr"))))
+                "09fsd0z6nhksc1h921h8q28f87hr6d1q8d6dmpxphjylb9r5xmj4"))))
     (build-system r-build-system)
     (home-page "http://yihui.name/formatR")
     (synopsis "Format R code automatically")
@@ -734,13 +740,13 @@ emitter (http://pyyaml.org/wiki/LibYAML) for R.")
 (define-public r-knitr
   (package
     (name "r-knitr")
-    (version "1.11")
+    (version "1.12.3")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "knitr" version))
               (sha256
                (base32
-                "1ikjla0hnpjfkdbydqhhqypc0aiizbi4nyn8c694sdk9ca4jasdd"))))
+                "1v3rzv6wq8mvpdrljsaqk4z3f8323jnv385js24wmn4fglqly6dz"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-evaluate" ,r-evaluate)
@@ -763,13 +769,13 @@ generation in R using Literate Programming techniques.")
 (define-public r-microbenchmark
   (package
     (name "r-microbenchmark")
-    (version "1.4-2")
+    (version "1.4-2.1")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "microbenchmark" version))
               (sha256
                (base32
-                "05yxvdnkxr2ll94h6f2m5sn3gg7vrlm9nbdxgmj2g8cp8gfxpfkg"))))
+                "0qn5r1a6qidghcisc2hpbdmj62pnixc3zz6p4ipk8mvakf0hdsvg"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-ggplot2" ,r-ggplot2)))
@@ -822,13 +828,13 @@ understand the language at a deeper level.")
 (define-public r-memoise
   (package
     (name "r-memoise")
-    (version "0.2.1")
+    (version "1.0.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "memoise" version))
               (sha256
                (base32
-                "19wm4b3kq6xva43kga3xydnl7ybl5mq7b4y2fczgzzjz63jd75y4"))))
+                "0sq2dhpvxy17v1baj256r0jnygdy3m5a8x4zh6vhv29957qnq6zx"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-digest" ,r-digest)))
@@ -862,20 +868,42 @@ New styles can also be created easily.  This package was inspired by the
 \"chalk\" JavaScript project.")
     (license license:expat)))
 
+(define-public r-praise
+  (package
+    (name "r-praise")
+    (version "1.0.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "praise" version))
+       (sha256
+        (base32
+         "1gfyypnvmih97p2r0php9qa39grzqpsdbq5g0fdsbpq5zms5w0sw"))))
+    (build-system r-build-system)
+    (home-page "https://github.com/gaborcsardi/praise")
+    (synopsis "Functions to praise users")
+    (description
+     "This package provides template functions to assist in building friendly
+R packages that praise their users.")
+    (license license:expat)))
+
 (define-public r-testthat
   (package
     (name "r-testthat")
-    (version "0.10.0")
+    (version "1.0.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "testthat" version))
               (sha256
                (base32
-                "0b3akwcx5mv9dmi8vssbk91hr3yrrdxd2fm6zhr31fnyz8kjx4pw"))))
+                "1ci1y54kaz7g4di79fcibp0m0wkkxn2glchhs6v8jfg6374ka410"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-digest" ,r-digest)
-       ("r-crayon" ,r-crayon)))
+       ("r-crayon" ,r-crayon)
+       ("r-magrittr" ,r-magrittr)
+       ("r-praise" ,r-praise)
+       ("r-r6" ,r-r6)))
     (home-page "https://github.com/hadley/testthat")
     (synopsis "Unit testing for R")
     (description
@@ -886,21 +914,14 @@ flexible and easy to set up.")
 (define-public r-r6
   (package
     (name "r-r6")
-    (version "2.1.1")
+    (version "2.1.2")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "R6" version))
               (sha256
                (base32
-                "16qq35bgxgswf989yvsqkb6fv7srpf8n8dv2s2c0z9n6zgmwq66m"))))
+                "0yad91i9p4r8bbz6nq8zny39y767n9an7ak5p275ynx8km6v3yqv"))))
     (build-system r-build-system)
-    (propagated-inputs
-     `(("r-knitr" ,r-knitr)
-       ("r-microbenchmark" ,r-microbenchmark)
-       ("r-pryr" ,r-pryr)
-       ("r-testthat" ,r-testthat)
-       ("r-ggplot2" ,r-ggplot2)
-       ("r-scales" ,r-scales)))
     (home-page "https://github.com/wch/R6/")
     (synopsis "Classes with reference semantics in R")
     (description
@@ -944,6 +965,110 @@ matter where it is stored, whether in a data frame, a data table or
 database.")
     (license license:expat)))
 
+(define-public r-acepack
+  (package
+    (name "r-acepack")
+    (version "1.3-3.3")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "acepack" version))
+       (sha256
+        (base32
+         "13ry3vyys12iplb14jfhmkrl9g5fxg3iijiggq4s4zb5m5436b1y"))))
+    (build-system r-build-system)
+    (inputs
+     `(("gfortran" ,gfortran)))
+    (home-page "http://cran.r-project.org/web/packages/acepack")
+    (synopsis "Functions for regression transformations")
+    (description
+     "This package provides ACE and AVAS methods for choosing regression
+transformations.")
+    (license license:expat)))
+
+(define-public r-cluster
+  (package
+    (name "r-cluster")
+    (version "2.0.4")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "cluster" version))
+       (sha256
+        (base32
+         "1r669aaaia05i8sv8hxiig1ddah7hm8qw869wgig5i0zzk22bnfl"))))
+    (build-system r-build-system)
+    (inputs
+     `(("gfortran" ,gfortran)))
+    (home-page "http://cran.r-project.org/web/packages/cluster")
+    (synopsis "Methods for data cluster analysis")
+    (description
+     "This package provides tools that are useful in finding groups in data.
+It is based on the methods described in Kaufman and Rousseeuw (1990) \"Finding
+Groups in Data\".")
+    (license license:gpl2+)))
+
+(define-public r-foreign
+  (package
+    (name "r-foreign")
+    (version "0.8-66")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "foreign" version))
+       (sha256
+        (base32
+         "19278jm85728zb20800w6hq9q8jy8ywdn81mgmlnxkmrr9giwh6p"))))
+    (build-system r-build-system)
+    (home-page "http://cran.r-project.org/web/packages/foreign")
+    (synopsis "Read data stored by other statistics software in R")
+    (description
+     "This package provides functions for reading and writing data stored by
+some versions of Epi Info, Minitab, S, SAS, SPSS, Stata, Systat and Weka, and
+for reading and writing some dBase files.")
+    (license license:gpl2+)))
+
+(define-public r-formula
+  (package
+    (name "r-formula")
+    (version "1.2-1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "Formula" version))
+       (sha256
+        (base32
+         "02in5325zzrqbhlygx6s0dinj6ymw845q70y56frqacv25ayzcax"))))
+    (properties `((upstream-name . "Formula")))
+    (build-system r-build-system)
+    (home-page "http://cran.r-project.org/web/packages/Formula")
+    (synopsis "Extended model formulas")
+    (description
+     "This package provides a new class @code{Formula}, which extends the base
+class @code{formula}.  It supports extended formulas with multiple parts of
+regressors on the right-hand side and/or multiple responses on the left-hand
+side.")
+    (license (list license:gpl2+ license:gpl3+))))
+
+(define-public r-locfit
+  (package
+    (name "r-locfit")
+    (version "1.5-9.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "locfit" version))
+       (sha256
+        (base32
+         "0lafrmq1q7x026m92h01hc9cjjiximqqi3v1g2hw7ai9vf7i897m"))))
+    (build-system r-build-system)
+    (home-page "http://cran.r-project.org/web/packages/locfit")
+    (synopsis "Local regression, likelihood and density estimation")
+    (description
+     "This package provides functions used for local regression, likelihood
+and density estimation.")
+    (license (list license:gpl2+ license:gpl3+))))
+
 (define-public r-chron
   (package
     (name "r-chron")
@@ -984,6 +1109,26 @@ fast ordered joins, fast add/modify/delete of columns by group, column listing
 and fast file reading.")
     (license license:gpl3+)))
 
+(define-public r-xtable
+  (package
+    (name "r-xtable")
+    (version "1.8-2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "xtable" version))
+       (sha256
+        (base32
+         "0398qkpvlw3dv0myz4mjcyqwpwc2m31l127r8vdzwc71wb6s28qn"))))
+    (build-system r-build-system)
+    (native-inputs
+     `(("r-knitr" ,r-knitr)))
+    (home-page "http://xtable.r-forge.r-project.org/")
+    (synopsis "Export R tables to LaTeX or HTML")
+    (description
+     "This package provides tools to export R data as LaTeX and HTML tables.")
+    (license license:gpl2+)))
+
 (define-public python-patsy
   (package
     (name "python-patsy")
@@ -1180,13 +1325,13 @@ module, Java Server Pages, and Python's psp module.")
 (define-public r-roxygen2
   (package
     (name "r-roxygen2")
-    (version "5.0.0")
+    (version "5.0.1")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "roxygen2" version))
               (sha256
                (base32
-                "0xjdphjs7l1v71lylmqgp76cbcxzvm9z1a40jgkdwvz072nn08vr"))))
+                "19gblyrrn29msbpawcb1hn5m1rshiqwxy0lby0vf92rm13fmsxcz"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-brew" ,r-brew)
@@ -1201,21 +1346,51 @@ module, Java Server Pages, and Python's psp module.")
 collation, and NAMESPACE files.")
     (license license:gpl2+)))
 
+(define-public r-openssl
+  (package
+    (name "r-openssl")
+    (version "0.9.2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "openssl" version))
+       (sha256
+        (base32
+         "1dbsaciz39zvsmcyxkmpfm5yxzrpw2iv2nb86525wn80q0cyv0cb"))))
+    (build-system r-build-system)
+    (inputs
+     `(("openssl" ,openssl)))
+    (home-page "https://github.com/jeroenooms/openssl")
+    (synopsis "Toolkit for encryption, signatures and certificates")
+    (description
+     "This package provides R bindings to OpenSSL libssl and libcrypto, plus
+custom SSH pubkey parsers.  It supports RSA, DSA and NIST curves P-256, P-384
+and P-521.  Cryptographic signatures can either be created and verified
+manually or via x509 certificates.  AES block cipher is used in CBC mode for
+symmetric encryption; RSA for asymmetric (public key) encryption.  High-level
+envelope functions combine RSA and AES for encrypting arbitrary sized data.
+Other utilities include key generators, hash functions (md5, sha1, sha256,
+etc), base64 encoder, a secure random number generator, and @code{bignum} math
+methods for manually performing crypto calculations on large multibyte
+integers.")
+    (license license:expat)))
+
 (define-public r-httr
   (package
     (name "r-httr")
-    (version "1.0.0")
+    (version "1.1.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "httr" version))
               (sha256
                (base32
-                "1yprw8p4g8026jhravgg1hdwj1g51cpdgycyr5a58jwm4i5f79cq"))))
+                "08sq34pknsfcy8lm06nydi12mbaxpqpgb025ahr33v9d3g0wvh6p"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-curl" ,r-curl)
        ("r-digest" ,r-digest)
        ("r-jsonlite" ,r-jsonlite)
+       ("r-openssl" ,r-openssl)
        ("r-mime" ,r-mime)
        ("r-r6" ,r-r6)
        ("r-stringr" ,r-stringr)))
@@ -1231,13 +1406,13 @@ functions make it easy to control additional request components.")
 (define-public r-git2r
   (package
     (name "r-git2r")
-    (version "0.11.0")
+    (version "0.14.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "git2r" version))
               (sha256
                (base32
-                "1h5ag8sm512jsn2sp4yhiqspc7hjq5y8z0kqz24sdznxa3b7rpn9"))))
+                "0jkkrggffpflaaw0gn2hnm1wz83xs31amriim481g73zf30g2bpr"))))
     (build-system r-build-system)
     ;; This R package contains modified sources of libgit2.  This modified
     ;; version of libgit2 is built as the package is built.  Hence libgit2 is
@@ -1257,13 +1432,13 @@ pure C implementation of the Git core methods.")
 (define-public r-rstudioapi
   (package
     (name "r-rstudioapi")
-    (version "0.3.1")
+    (version "0.5")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "rstudioapi" version))
               (sha256
                (base32
-                "0q7671d924nzqsqhs8d9p7l907bcam56wjwm7vvz44xgj0saj8bs"))))
+                "0sgnqfx0m3hzh57k10s7ndrbw7yqjjjcgfikafya98jcc7wmpwym"))))
     (build-system r-build-system)
     (home-page "http://cran.r-project.org/web/packages/rstudioapi")
     (synopsis "Safely access the RStudio API")
@@ -1275,13 +1450,13 @@ informative error messages when it's not available.")
 (define-public r-devtools
   (package
     (name "r-devtools")
-    (version "1.10.0")
+    (version "1.11.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "devtools" version))
               (sha256
                (base32
-                "11x51bqhjwypbxv5sfnrnxx06b92k8kzmmx7zrwk3537r072b6pa"))))
+                "101j15d0f9107pnmdpdwqyvk2ncykq48336rl8lnqp6idiq8id2q"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-curl" ,r-curl)
@@ -1346,13 +1521,13 @@ disk (or a connection).")
 (define-public r-plotrix
   (package
     (name "r-plotrix")
-    (version "3.6")
+    (version "3.6-1")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "plotrix" version))
               (sha256
                (base32
-                "0zn6k8azh40v0lg7q9yd4sy30a26bcc0fjvndn4z7k36avlw4i25"))))
+                "1y8xnlpy4zba70af9lwj2sshvfdfcmfdh92wamyzj8z9gciailfr"))))
     (build-system r-build-system)
     (home-page "http://cran.r-project.org/web/packages/plotrix")
     (synopsis "Various plotting functions")
@@ -1398,16 +1573,40 @@ multivariate data.  Lattice is sufficient for typical graphics needs, and is
 also flexible enough to handle most nonstandard requirements.")
     (license license:gpl2+)))
 
+(define-public r-latticeextra
+  (package
+    (name "r-latticeextra")
+    (version "0.6-28")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "latticeExtra" version))
+       (sha256
+        (base32
+         "1hkyqsa7klk5glj9y1hg3rxr5qilqw8h0017zc4c3nps7lr9a1kq"))))
+    (properties `((upstream-name . "latticeExtra")))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-lattice" ,r-lattice)
+       ("r-rcolorbrewer" ,r-rcolorbrewer)))
+    (home-page "http://latticeextra.r-forge.r-project.org/")
+    (synopsis "Extra graphical utilities based on lattice")
+    (description
+     "Building on the infrastructure provided by the lattice package, this
+package provides several new high-level graphics functions and methods, as
+well as additional utilities such as panel and axis annotation functions.")
+    (license license:gpl2+)))
+
 (define-public r-rcpparmadillo
   (package
     (name "r-rcpparmadillo")
-    (version "0.6.200.2.0")
+    (version "0.6.700.3.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "RcppArmadillo" version))
               (sha256
                (base32
-                "137wqqga776yj6synx5awhrzgkz7mmqnvgmggh9l4k6d99vwp9gj"))
+                "1mc62b6my568ni18w4clgs6l6ggqrwzsm3lgx0c1prf4rap69s8w"))
               (modules '((guix build utils)))
               ;; Remove bundled armadillo sources
               (snippet
@@ -1485,14 +1684,14 @@ encoder/decoder, round-off-error-free sum and cumsum, etc.")
 (define-public r-rmarkdown
   (package
     (name "r-rmarkdown")
-    (version "0.8.1")
+    (version "0.9.5")
     (source
       (origin
         (method url-fetch)
         (uri (cran-uri "rmarkdown" version))
         (sha256
           (base32
-            "07q5g9dvac5j3vnf4sjc60mnkij1k6y7vnzjz6anf499rwdwbxza"))))
+            "1zz98jxvw3lzva5kkj1n37gbhjwqd96gjs04y6h37pqy6qmkhk8c"))))
     (properties `((upstream-name . "rmarkdown")))
     (build-system r-build-system)
     (propagated-inputs
@@ -1511,13 +1710,13 @@ variety of formats.")
 (define-public r-gtable
   (package
     (name "r-gtable")
-    (version "0.1.2")
+    (version "0.2.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "gtable" version))
               (sha256
                (base32
-                "0k9hfj6r5y238gqh92s3cbdn34biczx3zfh79ix5xq0c5vkai2xh"))))
+                "0vz7073m0a2q12qzzihrfh5c2kx5jqi5l7z470fxmwqghdllh7l0"))))
     (properties `((upstream-name . "gtable")))
     (build-system r-build-system)
     (home-page "http://cran.r-project.org/web/packages/gtable")
@@ -1530,13 +1729,13 @@ grobs.")
 (define-public r-gridextra
   (package
     (name "r-gridextra")
-    (version "2.0.0")
+    (version "2.2.1")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "gridExtra" version))
               (sha256
                (base32
-                "19yyrfd37c5hxlavb9lca9l26wjhc80rlqhgmfj9k3xhbvvpdp17"))))
+                "0638ihwl00j76ivaxxhxvi8z573lwy1jym3srr78mx6dbdd4bzj4"))))
     (properties `((upstream-name . "gridExtra")))
     (build-system r-build-system)
     (propagated-inputs
@@ -1607,13 +1806,13 @@ ldap, and also supports cookies, redirects, authentication, etc.")
 (define-public r-xml
   (package
     (name "r-xml")
-    (version "3.98-1.3")
+    (version "3.98-1.4")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "XML" version))
               (sha256
                (base32
-                "0j9ayp8a35g0227a4zd8nbmvnbfnj5w687jal6qvj4lbhi3va7sy"))))
+                "09hiy5a875v2fhsgrsfymrwccn9249wnnsr6ck2slrig65svq2lw"))))
     (properties
      `((upstream-name . "XML")))
     (build-system r-build-system)
@@ -1629,6 +1828,34 @@ documents (including DTDs), both local and accessible via HTTP or FTP.  Also
 offers access to an XPath \"interpreter\".")
     (license license:bsd-2)))
 
+(define-public r-xnomial
+  (package
+    (name "r-xnomial")
+    (version "1.0.4")
+    (source
+     (origin (method url-fetch)
+             (uri (cran-uri "XNomial" version))
+             (sha256
+              (base32
+               "1mwx302576rmsjllbq2clfxilm3hkyp5bw0wmwqbn0kgv5wpy8z6"))))
+    (properties (quasiquote ((upstream-name . "XNomial"))))
+    (build-system r-build-system)
+    (home-page "http://cran.r-project.org/web/packages/XNomial")
+    (synopsis "Goodness-of-Fit test for multinomial data")
+    (description
+     "This package provides an exact Goodness-of-Fit test for
+multinomial data with fixed probabilities.  It can be used to
+determine whether a set of counts fits a given expected ratio.  To see
+whether a set of observed counts fits an expectation, one can examine
+all possible outcomes with @code{xmulti()} or a random sample of them
+with @code{xmonte()} and find the probability of an observation
+deviating from the expectation by at least as much as the observed.
+As a measure of deviation from the expected, one can use the
+log-likelihood ratio, the multinomial probability, or the classic
+chi-square statistic.  A histogram of the test statistic can also be
+plotted and compared with the asymptotic curve.")
+    (license (list license:gpl2+ license:gpl3+))))
+
 (define-public r-lambda-r
   (package
     (name "r-lambda-r")
@@ -1881,16 +2108,175 @@ The 'DataTables' library has been included in this R package.")
 flexible than the orphaned \"base64\" package.")
     (license license:gpl2+)))
 
+(define-public r-irlba
+  (package
+    (name "r-irlba")
+    (version "2.0.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "irlba" version))
+       (sha256
+        (base32
+         "1gms3rxrm24ri4vjvnpl4v47m7bx0zk63z8y85rbhsvx230xdy0m"))))
+    (build-system r-build-system)
+    (home-page "http://cran.r-project.org/web/packages/irlba")
+    (synopsis "Methods for eigendecomposition of large matrices")
+    (description
+     "This package provides fast and memory efficient methods for truncated
+singular and eigenvalue decompositions, as well as for principal component
+analysis of large sparse or dense matrices.")
+    (license (list license:gpl2+ license:gpl3+))))
+
+(define-public r-pkgmaker
+  (package
+    (name "r-pkgmaker")
+    (version "0.22")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "pkgmaker" version))
+       (sha256
+        (base32
+         "0vrqnd3kg6liqvpbd969jjsdx0f0rvmmxgdbwwrp6xfmdg0pib8r"))))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-codetools" ,r-codetools)
+       ("r-digest" ,r-digest)
+       ("r-registry" ,r-registry)
+       ("r-stringr" ,r-stringr)
+       ("r-xtable" ,r-xtable)))
+    (home-page "https://renozao.github.io/pkgmaker")
+    (synopsis "Package development utilities")
+    (description
+     "This package provides some low-level utilities to use for R package
+development.  It currently provides managers for multiple package specific
+options and registries, vignette, unit test and bibtex related utilities.")
+    (license license:gpl2+)))
+
+ (define-public r-registry
+   (package
+     (name "r-registry")
+     (version "0.3")
+     (source
+      (origin
+        (method url-fetch)
+        (uri (cran-uri "registry" version))
+        (sha256
+         (base32
+          "0c7lscfxncwwd8zp46h2xfw9gw14dypqv6m2kx85xjhjh0xw99aq"))))
+     (build-system r-build-system)
+     (home-page "http://cran.r-project.org/web/packages/registry")
+     (synopsis "Infrastructure for R package registries")
+     (description
+      "This package provides a generic infrastructure for creating and using R
+package registries.")
+     (license license:gpl2+)))
+
+(define-public r-rngtools
+  (package
+    (name "r-rngtools")
+    (version "1.2.4")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "rngtools" version))
+       (sha256
+        (base32
+         "1fcgfqrrb48z37xgy8sffx91p9irp39yqzxv7nqp1x2hnwsrh097"))))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-digest" ,r-digest)
+       ("r-pkgmaker" ,r-pkgmaker)
+       ("r-stringr" ,r-stringr)))
+    (home-page "https://renozao.github.io/rngtools")
+    (synopsis "Utility functions for working with random number generators")
+    (description
+     "This package contains a set of functions for working with Random Number
+Generators (RNGs).  In particular, it defines a generic S4 framework for
+getting/setting the current RNG, or RNG data that are embedded into objects
+for reproducibility.  Notably, convenient default methods greatly facilitate
+the way current RNG settings can be changed.")
+    (license license:gpl3+)))
+
+(define-public r-nmf
+  (package
+    (name "r-nmf")
+    (version "0.20.6")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "NMF" version))
+       (sha256
+        (base32
+         "0mmh9bz0zjwd8h9jplz4rq3g94npaqj8s4px51vcv47csssd9k6z"))))
+    (properties `((upstream-name . "NMF")))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-cluster" ,r-cluster)
+       ("r-colorspace" ,r-colorspace)
+       ("r-digest" ,r-digest)
+       ("r-doparallel" ,r-doparallel)
+       ("r-foreach" ,r-foreach)
+       ("r-ggplot2" ,r-ggplot2)
+       ("r-gridbase" ,r-gridbase)
+       ("r-pkgmaker" ,r-pkgmaker)
+       ("r-rcolorbrewer" ,r-rcolorbrewer)
+       ("r-registry" ,r-registry)
+       ("r-reshape2" ,r-reshape2)
+       ("r-rngtools" ,r-rngtools)
+       ("r-stringr" ,r-stringr)))
+    (home-page "http://renozao.github.io/NMF")
+    (synopsis "Algorithms and framework for nonnegative matrix factorization")
+    (description
+     "This package provides a framework to perform Non-negative Matrix
+Factorization (NMF).  The package implements a set of already published
+algorithms and seeding methods, and provides a framework to test, develop and
+plug new or custom algorithms.  Most of the built-in algorithms have been
+optimized in C++, and the main interface function provides an easy way of
+performing parallel computations on multicore machines.")
+    (license license:gpl2+)))
+
+(define-public r-igraph
+  (package
+    (name "r-igraph")
+    (version "1.0.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "igraph" version))
+       (sha256
+        (base32
+         "00jnm8v3kvxpxav5klld2z2nnkcpj4sdwv4ksipddy5mp04ysr6w"))))
+    (build-system r-build-system)
+    (native-inputs
+     `(("gfortran" ,gfortran)))
+    (inputs
+     `(("gmp" ,gmp)
+       ("libxml2" ,libxml2)))
+    (propagated-inputs
+     `(("r-irlba" ,r-irlba)
+       ("r-magrittr" ,r-magrittr)
+       ("r-nmf" ,r-nmf)))
+    (home-page "http://igraph.org")
+    (synopsis "Network analysis and visualization")
+    (description
+     "This package provides routines for simple graphs and network analysis.
+It can handle large graphs very well and provides functions for generating
+random and regular graphs, graph visualization, centrality methods and much
+more.")
+    (license license:gpl2+)))
+
 (define-public r-r-methodss3
   (package
     (name "r-r-methodss3")
-    (version "1.7.0")
+    (version "1.7.1")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "R.methodsS3" version))
               (sha256
                (base32
-                "1dg4bbrwr8jcsqisjrrwxs942mrjq72zw8yvl2br4djdm0md8zz5"))))
+                "11z6v2i7jl647wxi9p5z66yvfnnqv6s7fxqmz7w2gkb6j8wl1f24"))))
     (properties `((upstream-name . "R.methodsS3")))
     (build-system r-build-system)
     (home-page "http://cran.r-project.org/web/packages/R.methodsS3")
@@ -1908,13 +2294,13 @@ want to migrate to S4.")
 (define-public r-r-oo
   (package
     (name "r-r-oo")
-    (version "1.19.0")
+    (version "1.20.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "R.oo" version))
               (sha256
                (base32
-                "15rm1qb9a212bqazhcpk7m48hcp7jq8rh4yhd9c6zfyvdqszfmsb"))))
+                "1l1x4r69mdchjyi6sq52p580fz3b3bqv6dpn1706y9n4vq47qx24"))))
     (properties `((upstream-name . "R.oo")))
     (build-system r-build-system)
     (propagated-inputs
@@ -1931,13 +2317,13 @@ maintenance for package developers.")
 (define-public r-r-utils
   (package
     (name "r-r-utils")
-    (version "2.1.0")
+    (version "2.3.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "R.utils" version))
               (sha256
                (base32
-                "03pi6pkcsq65fv7cn4x74cj050dc8x5d4xyg930p6f7flk788xaz"))))
+                "0f4z7ka1wb7bgxc5wyqihqxsnqwgyyzbglwvfwmx0gn8i0wzi647"))))
     (properties `((upstream-name . "R.utils")))
     (build-system r-build-system)
     (propagated-inputs
@@ -1979,13 +2365,13 @@ persistent (on the file system).")
 (define-public r-r-rsp
   (package
     (name "r-r-rsp")
-    (version "0.20.0")
+    (version "0.21.0")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "R.rsp" version))
               (sha256
                (base32
-                "06vq9qq5hdz3hqc99q82622mab6ix7jwap20h4za6ap6gnwqs0fv"))))
+                "0snc6ps75s3ci6sy8mil1wg2i9xmlr1ygh9n244y1brdvp43dfsw"))))
     (properties `((upstream-name . "R.rsp")))
     (build-system r-build-system)
     (propagated-inputs
@@ -2010,13 +2396,13 @@ vignettes.")
 (define-public r-matrixstats
   (package
     (name "r-matrixstats")
-    (version "0.15.0")
+    (version "0.50.1")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "matrixStats" version))
               (sha256
                (base32
-                "1068k85s6rlwfzlszw790c2rndydvrsw7rpck6k6z17896m8drfa"))))
+                "08l32abp7dfnsc49ca4hzznh934y60n5z01x5ga2ixky5961s57c"))))
     (properties `((upstream-name . "matrixStats")))
     (build-system r-build-system)
     (native-inputs
@@ -2034,13 +2420,13 @@ memory usage.")
 (define-public r-viridis
   (package
     (name "r-viridis")
-    (version "0.3.1")
+    (version "0.3.4")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "viridis" version))
               (sha256
                (base32
-                "0zz9i874s1fwhl9bcbiprlzaz7zsy1rj6c729zn3k525d63qbnj7"))))
+                "1a9hqn2pccpc51vh8ghw698ni6xzdnp8v0n8kgjh51nlz5hhc87j"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-ggplot2" ,r-ggplot2)
@@ -2057,26 +2443,81 @@ black-and-white.  They are also designed to be perceived by readers with the
 most common form of color blindness.")
     (license license:x11)))
 
+(define-public r-tidyr
+  (package
+    (name "r-tidyr")
+    (version "0.4.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "tidyr" version))
+       (sha256
+        (base32
+         "0xp6lyr2l4ix2mrilx4qmca7wm5qmbhvi24m4nf7qsgwp54gnv2h"))))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-dplyr" ,r-dplyr)
+       ("r-lazyeval" ,r-lazyeval)
+       ("r-magrittr" ,r-magrittr)
+       ("r-rcpp" ,r-rcpp)
+       ("r-stringi" ,r-stringi)))
+    (home-page "https://github.com/hadley/tidyr")
+    (synopsis "Tidy data with `spread()` and `gather()` functions")
+    (description
+     "tidyr is a reframing of the reshape2 package designed to accompany the
+tidy data framework, and to work hand-in-hand with magrittr and dplyr to build
+a solid pipeline for data analysis.  It is designed specifically for tidying
+data, not the general reshaping that reshape2 does, or the general aggregation
+that reshape did.  In particular, built-in methods only work for data frames,
+and tidyr provides no margins or aggregation.")
+    (license license:expat)))
+
+(define-public r-hexbin
+  (package
+    (name "r-hexbin")
+    (version "1.27.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (cran-uri "hexbin" version))
+       (sha256
+        (base32
+         "0xi6fbf1fvyn2gffr052n3viibqzpr3603sgi4xaminbzja4syjh"))))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-lattice" ,r-lattice)))
+    (native-inputs
+     `(("gfortran" ,gfortran)))
+    (home-page "http://github.com/edzer/hexbin")
+    (synopsis "Hexagonal binning routines")
+    (description
+     "This package provides binning and plotting functions for hexagonal bins.
+It uses and relies on grid graphics and formal (S4) classes and methods.")
+    (license license:gpl2+)))
+
 (define-public r-plotly
   (package
     (name "r-plotly")
-    (version "2.0.3")
+    (version "3.4.13")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "plotly" version))
               (sha256
                (base32
-                "16pqycns8qf0y1j21n009qf242lv0izwyidlx40zv88izxhg1vs0"))))
+                "1pfl9w35iwin8a1hfwcihajyps2ngjbyrmvi61b9lspcdbk39lf8"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-base64enc" ,r-base64enc)
        ("r-digest" ,r-digest)
        ("r-ggplot2" ,r-ggplot2)
+       ("r-hexbin" ,r-hexbin)
        ("r-htmlwidgets" ,r-htmlwidgets)
        ("r-httr" ,r-httr)
        ("r-jsonlite" ,r-jsonlite)
        ("r-magrittr" ,r-magrittr)
        ("r-plyr" ,r-plyr)
+       ("r-scales" ,r-scales)
+       ("r-tidyr" ,r-tidyr)
        ("r-viridis" ,r-viridis)))
     (home-page "https://plot.ly/r")
     (synopsis "Create interactive web graphics")
diff --git a/gnu/packages/tcl.scm b/gnu/packages/tcl.scm
index 1f301458a9..993842339b 100644
--- a/gnu/packages/tcl.scm
+++ b/gnu/packages/tcl.scm
@@ -45,7 +45,7 @@
               (sha256
                (base32
                 "13cwa4bc85ylf5gfj9vk182lvgy60qni3f7gbxghq78wk16djvly"))
-              (patches (list (search-patch "tcl-mkindex-deterministic.patch")))))
+              (patches (search-patches "tcl-mkindex-deterministic.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-cons-before
@@ -143,7 +143,7 @@ X11 GUIs.")
              (sha256
               (base32
                "1h96vp15zl5xz0d4qp6wjyrchqmrmdm3q5k22wkw9jaxbvw9vy88"))
-             (patches (list (search-patch "tk-find-library.patch")))))
+             (patches (search-patches "tk-find-library.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (modify-phases %standard-phases
@@ -257,7 +257,7 @@ utility functions and modules all written in high-level Tcl.")
               (sha256
                (base32
                 "0ffb4aw63inig3aql33g4pk0kjk14dv238anp1scwjdjh1k6n4gl"))
-              (patches (list (search-patch "tclxml-3.2-install.patch")))))
+              (patches (search-patches "tclxml-3.2-install.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("tcl" ,tcl)
diff --git a/gnu/packages/tcsh.scm b/gnu/packages/tcsh.scm
index 0bd1b92b8f..5e3df2ba3f 100644
--- a/gnu/packages/tcsh.scm
+++ b/gnu/packages/tcsh.scm
@@ -40,7 +40,7 @@
               (sha256
                (base32
                 "1a4z9kwgx1iqqzvv64si34m60gj34p7lp6rrcrb59s7ka5wa476q"))
-              (patches (list (search-patch "tcsh-fix-autotest.patch")))
+              (patches (search-patches "tcsh-fix-autotest.patch"))
               (patch-flags '("-p0"))))
     (build-system gnu-build-system)
     (inputs
diff --git a/gnu/packages/telephony.scm b/gnu/packages/telephony.scm
index 76e369a563..50a83fbcf3 100644
--- a/gnu/packages/telephony.scm
+++ b/gnu/packages/telephony.scm
@@ -76,7 +76,8 @@ to facilitate using C++ design patterns even for very deeply embedded
 applications, such as for systems using uclibc along with posix threading
 support.")
    (license gpl3+)
-   (home-page "http://www.gnu.org/software/commoncpp")))
+   (home-page "http://www.gnu.org/software/commoncpp")
+   (properties '((ftp-directory . "/gnu/commoncpp")))))
 
 (define-public ccrtp
   (package
diff --git a/gnu/packages/texinfo.scm b/gnu/packages/texinfo.scm
index 18142adb1a..d645ef4bc1 100644
--- a/gnu/packages/texinfo.scm
+++ b/gnu/packages/texinfo.scm
@@ -136,8 +136,8 @@ is on expressing the content semantically, avoiding physical markup commands.")
                (base32
                 "1yprv64vrlcbksqv25asplnjg07mbq38lfclp1m5lj8cw878pag8"))
               (patches
-               (list (search-patch "texi2html-document-encoding.patch")
-                     (search-patch "texi2html-i18n.patch")))
+               (search-patches "texi2html-document-encoding.patch"
+                               "texi2html-i18n.patch"))
               (snippet
                ;; This file is modified by the patch above, but reset its
                ;; timestamp so we don't trigger the rule to update PO files,
diff --git a/gnu/packages/textutils.scm b/gnu/packages/textutils.scm
index 71cf25b224..f6735a43e0 100644
--- a/gnu/packages/textutils.scm
+++ b/gnu/packages/textutils.scm
@@ -292,3 +292,39 @@ as existing hashing techniques, with provably negligible risk of collisions.")
 characteristic of this library is that different character encoding for every
 regular expression object can be specified.")
     (license license:bsd-2)))
+
+(define-public antiword
+  (package
+    (name "antiword")
+    (version "0.37")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://www.winfield.demon.nl/linux"
+                                  "/antiword-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1b7mi1l20jhj09kyh0bq14qzz8vdhhyf35gzwsq43mn6rc7h0b4f"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f ; There are no tests
+       #:make-flags
+       (list "-f" "Makefile.Linux"
+             (string-append "GLOBAL_INSTALL_DIR="
+                            (assoc-ref %outputs "out") "/bin")
+             (string-append "GLOBAL_RESOURCES_DIR="
+                            (assoc-ref %outputs "out") "/share/antiword"))
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)
+         (replace 'install
+           (lambda* (#:key make-flags #:allow-other-keys)
+             (zero? (apply system* "make" `("global_install" ,@make-flags))))))))
+    (home-page "http://www.winfield.demon.nl/")
+    (synopsis "Microsoft Word document reader")
+    (description "Antiword is an application for displaying Microsoft Word
+documents.  It can also convert the document to PostScript or XML.  Only
+documents made by MS Word version 2 and version 6 or later are supported.  The
+name comes from: \"The antidote against people who send Microsoft Word files
+to everybody, because they believe that everybody runs Windows and therefore
+runs Word\".")
+    (license license:gpl2+)))
diff --git a/gnu/packages/tls.scm b/gnu/packages/tls.scm
index 61fb651552..4ec0ed7d34 100644
--- a/gnu/packages/tls.scm
+++ b/gnu/packages/tls.scm
@@ -65,8 +65,22 @@
 for transmitting machine-neutral encodings of data objects in computer
 networking, allowing for formal validation of data according to some
 specifications.")
+    (replacement libtasn1/fixed)
     (license license:lgpl2.0+)))
 
+(define libtasn1/fixed                            ;for CVE-2016-4008
+  (package
+    (inherit libtasn1)
+    (source
+     (let ((version "4.8"))
+       (origin
+         (method url-fetch)
+         (uri (string-append "mirror://gnu/libtasn1/libtasn1-"
+                             version ".tar.gz"))
+         (sha256
+          (base32
+           "04y5m29pqmvkfdbppmsdifyx89v8xclxzklpfc7a1fkr9p4jz07s")))))))
+
 (define-public p11-kit
   (package
     (name "p11-kit")
@@ -176,7 +190,9 @@ living in the same process.")
 and DTLS protocols.  It is provided in the form of a C library to support the
 protocols, as well as to parse and write X.5009, PKCS 12, OpenPGP and other
 required structures.")
-    (license license:lgpl2.1+)))
+    (license license:lgpl2.1+)
+    (properties '((ftp-server . "ftp.gnutls.org")
+                  (ftp-directory . "/gcrypt/gnutls")))))
 
 (define-public openssl
   (package
@@ -192,9 +208,8 @@ required structures.")
              (sha256
               (base32
                "0cxajjayi859czi545ddafi24m9nwsnjsw4q82zrmqvwj2rv315p"))
-             (patches (map search-patch
-                           '("openssl-runpath.patch"
-                             "openssl-c-rehash-in.patch")))))
+             (patches (search-patches "openssl-runpath.patch"
+                                      "openssl-c-rehash-in.patch"))))
    (build-system gnu-build-system)
    (native-inputs `(("perl" ,perl)))
    (arguments
@@ -326,13 +341,13 @@ security, and applying best practice development processes.")
 (define-public python-acme
   (package
     (name "python-acme")
-    (version "0.4.2")
+    (version "0.5.0")
     (source (origin
       (method url-fetch)
       (uri (pypi-uri "acme" version))
       (sha256
         (base32
-         "1dh0qlsi309b37wa0nw0h2gvs94yk12lc4mhr3rb9c4h46m0hn8a"))))
+         "1g8scfkhs3l06588h73py81xb1gvkkdzaxanl21whcvdclycc186"))))
     (build-system python-build-system)
     (arguments
      `(#:phases
@@ -385,13 +400,13 @@ security, and applying best practice development processes.")
 (define-public letsencrypt
   (package
     (name "letsencrypt")
-    (version "0.4.2")
+    (version "0.5.0")
     (source (origin
               (method url-fetch)
               (uri (pypi-uri "letsencrypt" version))
               (sha256
                (base32
-                "1rjbblj60w7jwc5y04sy6fbxcynvakvazikg1pdmhyic5jmj9bg3"))))
+                "0nnijs26kkw07yylszc97p3jw09y98j54xihjp0rprrbp1q2p2p3"))))
     (build-system python-build-system)
     (arguments
      `(#:python ,python-2
diff --git a/gnu/packages/tor.scm b/gnu/packages/tor.scm
index 5fb8f954aa..5155fc09a0 100644
--- a/gnu/packages/tor.scm
+++ b/gnu/packages/tor.scm
@@ -80,7 +80,7 @@ applications based on the TCP protocol.")
                (base32
                 "0an2q5ail9z414riyjbkjkm29504hy778j914baz2gn5hlv2cfak"))
               (file-name (string-append name "-" version "-checkout"))
-              (patches (list (search-patch "torsocks-dns-test.patch")))))
+              (patches (search-patches "torsocks-dns-test.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (modify-phases %standard-phases
diff --git a/gnu/packages/tv.scm b/gnu/packages/tv.scm
index 0a229e149a..f58c03623e 100644
--- a/gnu/packages/tv.scm
+++ b/gnu/packages/tv.scm
@@ -39,10 +39,10 @@
               (sha256
                (base32
                 "08q5gzbyz0lxb730rz6d6amkzimlc7nanv6n50j2bpw4n2xa9wmf"))
-              (patches (list (search-patch "tvtime-videodev2.patch")
-                             (search-patch "tvtime-pngoutput.patch")
-                             (search-patch "tvtime-xmltv.patch")
-                             (search-patch "tvtime-gcc41.patch")))))
+              (patches (search-patches "tvtime-videodev2.patch"
+                                       "tvtime-pngoutput.patch"
+                                       "tvtime-xmltv.patch"
+                                       "tvtime-gcc41.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("libx11" ,libx11)
diff --git a/gnu/packages/valgrind.scm b/gnu/packages/valgrind.scm
index 5cfbe6d554..ed847c2def 100644
--- a/gnu/packages/valgrind.scm
+++ b/gnu/packages/valgrind.scm
@@ -38,7 +38,7 @@
              (sha256
               (base32
                "0hiv871b9bk689mv42mkhp76za78l5773glszfkdbpf1m1qn4fbc"))
-             (patches (map search-patch '("valgrind-enable-arm.patch")))))
+             (patches (search-patches "valgrind-enable-arm.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-cons-after
diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scm
index 0b70d545b9..94339012f5 100644
--- a/gnu/packages/version-control.scm
+++ b/gnu/packages/version-control.scm
@@ -4,8 +4,8 @@
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2013, 2014 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015 Mathieu Lirzin <mthl@openmailbox.org>
-;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2014, 2016 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2015 Kyle Meyer <kyle@kyleam.com>
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
@@ -29,7 +29,7 @@
   #:use-module ((guix licenses)
                 #:select (asl2.0 bsd-2
                           gpl1+ gpl2 gpl2+ gpl3+ lgpl2.1
-                          x11-style))
+                          public-domain x11-style))
   #:use-module (guix utils)
   #:use-module (guix packages)
   #:use-module (guix download)
@@ -38,7 +38,6 @@
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system python)
   #:use-module (guix build-system trivial)
-  #:use-module (guix build utils)
   #:use-module (gnu packages apr)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages asciidoc)
@@ -113,14 +112,14 @@ as well as the classic centralized workflow.")
   ;; Keep in sync with 'git-manpages'!
   (package
    (name "git")
-   (version "2.7.3")
+   (version "2.7.4")
    (source (origin
             (method url-fetch)
             (uri (string-append "mirror://kernel.org/software/scm/git/git-"
                                 version ".tar.xz"))
             (sha256
              (base32
-              "1di96q86fq3pdn5d5v4fw9vf58gha5i9b3r880mxlh275n8ngi49"))))
+              "0ys55v2xrhzj74jrrqx75xpr458klnyxshh8d8swfpp0zgg79rfy"))))
    (build-system gnu-build-system)
    (native-inputs
     `(("native-perl" ,perl)
@@ -292,7 +291,7 @@ everything from small to very large projects with speed and efficiency.")
                     version ".tar.xz"))
               (sha256
                (base32
-                "0va9j0q9h44jqih38h4cmhvbmjppqq7zbiq70220m7hsqqkq824z"))))
+                "09ffk5c0dl1xg7xcvr0kadhspx4fr2spmlmcajzfycmap0ddhkyh"))))
     (build-system trivial-build-system)
     (arguments
      '(#:modules ((guix build utils))
@@ -681,14 +680,14 @@ property manipulation.")
 (define-public subversion
   (package
     (name "subversion")
-    (version "1.8.15")
+    (version "1.8.16")
     (source (origin
              (method url-fetch)
              (uri (string-append "http://archive.apache.org/dist/subversion/"
                                  "subversion-" version ".tar.bz2"))
              (sha256
               (base32
-               "0b68rjy1sjd66nqcswrm1bhda3vk2ngkgs6drcanmzbcd3vs366g"))))
+               "0imkxn25n6sbcgfldrx4z29npjprb1lxjm5fb89q4297161nx3zi"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-cons-after
@@ -896,8 +895,8 @@ large, complex patch files.")
               (sha256
                (base32
                 "0bkw6fjh20ppvn54smv05461lm1vcwvn02avx941c4acafmkl1cm"))
-              (patches (list (search-patch "cssc-gets-undeclared.patch")
-                             (search-patch "cssc-missing-include.patch")))))
+              (patches (search-patches "cssc-gets-undeclared.patch"
+                                       "cssc-missing-include.patch"))))
     (build-system gnu-build-system)
     (arguments
      `(#:phases (alist-cons-before
@@ -940,11 +939,11 @@ accessed and migrated on modern systems.")
               (sha256
                (base32
                 "18s86ssarfmc4l17gbpzybca29m5wa37cbaimdji8czlcry3mcjl"))
-            (patches (list (search-patch "aegis-perl-tempdir1.patch")
-                           (search-patch "aegis-perl-tempdir2.patch")
-                           (search-patch "aegis-test-fixup-1.patch")
-                           (search-patch "aegis-test-fixup-2.patch")
-                           (search-patch "aegis-constness-error.patch")))))
+            (patches (search-patches "aegis-perl-tempdir1.patch"
+                                     "aegis-perl-tempdir2.patch"
+                                     "aegis-test-fixup-1.patch"
+                                     "aegis-test-fixup-2.patch"
+                                     "aegis-constness-error.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("e2fsprogs" ,e2fsprogs)
@@ -1125,3 +1124,78 @@ Mercurial, Bazaar, Darcs, CVS, Fossil, and Veracity.")
      "This package allows you to use your hubic account as a \"special
 repository\" with git-annex.")
     (license gpl3+)))
+
+(define-public fossil
+  (package
+    (name "fossil")
+    (version "1.34")
+    (source
+     (origin
+       (method url-fetch)
+       ;; Upstream source affected by
+       ;; http://debbugs.gnu.org/cgi/bugreport.cgi?bug=20962
+       (uri (string-append
+             "https://web.archive.org/web/20160402202958/"
+             "https://www.fossil-scm.org/download/fossil-src-"
+             version ".tar.gz"))
+       (sha256
+        (base32
+         "17x4vgjcfihwmq195qg32irp50panvjqfpvhqydfvv4ghwzbi9jk"))
+       (modules '((guix build utils)))
+       (snippet
+        '(begin
+           ;; Commit 0a2ebe57 on 2015-08-03 18:35:53 changed output formatting
+           ;; for some commands, but affected tests were not updated.  Use
+           ;; substitute here, which is more concise than patching.
+           (substitute* "test/clean.test"
+             (("NEW ") "NEW    "))
+           (substitute* '("test/revert.test" "test/mv-rm.test")
+             (("REVERTED:") "REVERT  ")
+             (("DELETE:")   "DELETE  ")
+             (("UNMANAGE:") "UNMANAGE "))
+           ;; Fix use of __DATE__ and __TIME__
+           (substitute* "src/main.c"
+             (("Compiled on %s %s") "Compiled")
+             (("__DATE__, __TIME__, ") ""))
+           #t))
+       (patches (list (search-patch "fossil-test-fixes.patch")))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("tcl" ,tcl)                     ;for configuration only
+       ("which" ,which)                 ;for tests only
+       ("ed" ,ed)))                     ;ditto
+    (inputs
+     `(("openssl" ,openssl)
+       ("zlib" ,zlib)
+       ("sqlite" ,sqlite)))
+    (arguments
+     `(#:configure-flags (list "--with-openssl=auto"
+                               "--disable-internal-sqlite")
+       #:test-target "test"
+       #:phases (modify-phases %standard-phases
+                  (replace 'configure
+                    (lambda* (#:key outputs (configure-flags '())
+                                    #:allow-other-keys)
+                      ;; The 'configure' script is not an autoconf script and
+                      ;; chokes on unrecognized options.
+                      (zero? (apply system*
+                                    "./configure"
+                                    (string-append "--prefix="
+                                                   (assoc-ref outputs "out"))
+                                    configure-flags))))
+                  (add-before 'check 'test-setup
+                    (lambda _
+                      (setenv "USER" "guix")
+                      (setenv "TZ" "UTC")
+                      ;; Fixing the th1 test would require many backports, so
+                      ;; just disable for now.
+                      (delete-file "test/th1.test")
+                      #t)))))
+    (home-page "https://fossil-scm.org")
+    (synopsis "Software configuration management system")
+    (description
+     "Fossil is a distributed source control management system which supports
+access and administration over HTTP CGI or via a built-in HTTP server.  It has
+a built-in wiki, built-in file browsing, built-in tickets system, etc.")
+    (license (list public-domain        ;src/miniz.c, src/shell.c
+                   bsd-2))))
diff --git a/gnu/packages/video.scm b/gnu/packages/video.scm
index 8f93950e97..6060702022 100644
--- a/gnu/packages/video.scm
+++ b/gnu/packages/video.scm
@@ -62,6 +62,7 @@
   #:use-module (gnu packages ocr)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages popt)
   #:use-module (gnu packages pulseaudio)
   #:use-module (gnu packages python)
   #:use-module (gnu packages qt)
@@ -132,10 +133,10 @@ old-fashioned output methods with powerful ascii-art renderer.")
               (sha256
                (base32
                 "0czccp4fcpf2ykp16xcrzdfmnircz1ynhls334q374xknd5747d2"))
-              (patches (map search-patch '("liba52-enable-pic.patch"
-                                           "liba52-set-soname.patch"
-                                           "liba52-use-mtune-not-mcpu.patch"
-                                           "liba52-link-with-libm.patch")))))
+              (patches (search-patches "liba52-enable-pic.patch"
+                                       "liba52-set-soname.patch"
+                                       "liba52-use-mtune-not-mcpu.patch"
+                                       "liba52-link-with-libm.patch"))))
     (build-system gnu-build-system)
     ;; XXX We need to run ./bootstrap because of the build system fixes above.
     (native-inputs
@@ -535,6 +536,26 @@ convert and stream audio and video.  It includes the libavcodec
 audio/video codec library.")
     (license license:gpl2+)))
 
+(define-public ffmpeg-2.8
+  (package
+    (inherit ffmpeg)
+    (version "2.8.6")
+    (source (origin
+             (method url-fetch)
+             (uri (string-append "https://ffmpeg.org/releases/ffmpeg-"
+                                 version ".tar.xz"))
+             (sha256
+              (base32
+               "1yh7dvm7zwdlsspdaq524s5qaggma5md9h95qc4kvb5dmyyyvg15"))))
+    (arguments
+     (substitute-keyword-arguments (package-arguments ffmpeg)
+       ((#:configure-flags flags)
+        `(map (lambda (flag)
+                (if (string=? flag "--disable-mipsdsp")
+                    "--disable-mipsdspr1"
+                    flag))
+              ,flags))))))
+
 (define-public vlc
   (package
     (name "vlc")
@@ -546,7 +567,14 @@ audio/video codec library.")
                    version "/vlc-" version ".tar.xz"))
              (sha256
               (base32
-               "1jqzrzrpw6932lbkf863xk8cfmn4z2ngbxz7w8ggmh4f6xz9sgal"))))
+               "1jqzrzrpw6932lbkf863xk8cfmn4z2ngbxz7w8ggmh4f6xz9sgal"))
+             (modules '((guix build utils)))
+             (snippet
+              ;; There are two occurrences where __DATE__ and __TIME__ are
+              ;; used to capture the build time and show it to the user.
+              '(substitute* (find-files "." "help\\.c(pp)?$")
+                 (("__DATE__") "\"2016\"")
+                 (("__TIME__") "\"00:00\"")))))
     (build-system gnu-build-system)
     (native-inputs
      `(("git" ,git) ; needed for a test
@@ -557,7 +585,7 @@ audio/video codec library.")
        ("avahi" ,avahi)
        ("dbus" ,dbus)
        ("flac" ,flac)
-       ("ffmpeg" ,ffmpeg)
+       ("ffmpeg" ,ffmpeg-2.8)               ;fails to build against ffmpeg 3.0
        ("fontconfig" ,fontconfig)
        ("freetype" ,freetype)
        ("gnutls" ,gnutls)
@@ -591,7 +619,30 @@ audio/video codec library.")
        `("--disable-a52" ; FIXME: reenable once available
          ,(string-append "LDFLAGS=-Wl,-rpath -Wl,"
                          (assoc-ref %build-inputs "ffmpeg")
-                         "/lib")))) ; needed for the tests
+                         "/lib"))                 ;needed for the tests
+
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'install 'regenerate-plugin-cache
+           (lambda* (#:key outputs #:allow-other-keys)
+             ;; The 'install-exec-hook' rule in the top-level Makefile.am
+             ;; generates 'lib/vlc/plugins/plugins.dat', a plugin cache, using
+             ;; 'vlc-cache-gen'.  This file includes the mtime of the plugins
+             ;; it references.  Thus, we first reset the timestamps of all
+             ;; these files, and then regenerate the cache such that the
+             ;; mtimes it includes are always zero instead of being dependent
+             ;; on the build time.
+             (let* ((out       (assoc-ref outputs "out"))
+                    (pkglibdir (string-append out "/lib/vlc"))
+                    (plugindir (string-append pkglibdir "/plugins"))
+                    (cachegen  (string-append pkglibdir "/vlc-cache-gen")))
+               ;; TODO: Factorize 'reset-timestamps'.
+               (for-each (lambda (file)
+                           (let ((s (lstat file)))
+                             (unless (eq? (stat:type s) 'symlink)
+                               (utime file 0 0 0 0))))
+                         (find-files plugindir))
+               (zero? (system* cachegen plugindir))))))))
     (home-page "https://www.videolan.org/")
     (synopsis "Audio and video framework")
     (description "VLC is a cross-platform multimedia player and framework
@@ -696,7 +747,7 @@ SVCD, DVD, 3ivx, DivX 3/4/5, WMV and H.264 movies.")
 (define-public mpv
   (package
     (name "mpv")
-    (version "0.16.0")
+    (version "0.17.0")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -704,7 +755,7 @@ SVCD, DVD, 3ivx, DivX 3/4/5, WMV and H.264 movies.")
                     ".tar.gz"))
               (sha256
                (base32
-                "1fiqxx85s418qynq2fp0v7cpzrz8j285hwmc4fqgn5ny1vg1jdpw"))
+                "0vms3viwqcwl1mrgmf2yy4c69fvv7xpbkyrl693l6zpwynqd4b30"))
               (file-name (string-append name "-" version ".tar.gz"))))
     (build-system waf-build-system)
     (native-inputs
@@ -809,7 +860,7 @@ projects while introducing many more.")
 (define-public youtube-dl
   (package
     (name "youtube-dl")
-    (version "2016.03.01")
+    (version "2016.04.06")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://youtube-dl.org/downloads/"
@@ -817,9 +868,8 @@ projects while introducing many more.")
                                   version ".tar.gz"))
               (sha256
                (base32
-                "0w2dy54rnsi8fbzpnf07lpn3zzv5lhdfscanld4ai0rrrzmrl3zw"))))
+                "1kdrjwrn0x1wmvansvd2222gfqnld4zdihf2jwnz36112r1p8nhi"))))
     (build-system python-build-system)
-    (native-inputs `(("python-setuptools" ,python-setuptools)))
     (home-page "http://youtube-dl.org")
     (arguments
      ;; The problem here is that the directory for the man page and completion
@@ -1008,7 +1058,7 @@ for use with HTML5 video.")
              (sha256
               (base32
                "1vas43bwb15q2wv3dpp7fgp8dc6szinmwl7i0ziq2vv5l2128v0p"))
-             (patches (map search-patch '("avidemux-install-to-lib.patch")))))
+             (patches (search-patches "avidemux-install-to-lib.patch"))))
     (build-system cmake-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
@@ -1205,11 +1255,8 @@ and custom quantization matrices.")
     (build-system python-build-system)
     (arguments
      '(#:tests? #f)) ; tests rely on external web servers
-    (native-inputs
-     `(("python-setuptools" ,python-setuptools)))
     (propagated-inputs
-     `(("python-requests" ,python-requests)
-       ("python-singledispatch" ,python-singledispatch)))
+     `(("python-requests" ,python-requests)))
     (synopsis "Internet video stream viewer")
     (description "Livestreamer is a command-line utility that extracts streams
 from various services and pipes them into a video playing application.")
@@ -1386,3 +1433,33 @@ present in modern GPUs.")
     (description "Vdpauinfo is a tool to query the capabilities of a VDPAU
 implementation.")
     (license (license:x11-style "file://COPYING"))))
+
+(define-public recordmydesktop
+  (package
+    (name "recordmydesktop")
+    (version "0.3.8.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://sourceforge/" name "/" name "/"
+                                  version "/recordmydesktop-" version ".tar.gz"))
+              (sha256
+               (base32
+                "133kkl5j0r877d41bzj7kj0vf3xm8x80yyx2n8nqxrva304f58ik"))))
+    (build-system gnu-build-system)
+    (inputs `(("popt" ,popt)
+              ("zlib" ,zlib)
+              ("libx11" ,libx11)
+              ("libice" ,libice)
+              ("libsm" ,libsm)
+              ("libxfixes" ,libxfixes)
+              ("libxdamage" ,libxdamage)
+              ("libxext" ,libxext)
+              ("libvorbis" ,libvorbis)
+              ("libtheora" ,libtheora)))
+    (home-page "http://recordmydesktop.sourceforge.net/")
+    (synopsis "Desktop session video recorder")
+    (description
+     "recordMyDesktop is a command-line tool that captures the activity in
+your graphical desktop and encodes it as a video.  This is a useful tool for
+making @dfn{screencasts}.")
+    (license license:gpl2+)))
diff --git a/gnu/packages/vpn.scm b/gnu/packages/vpn.scm
index 34dacecdc5..d7c2616dfe 100644
--- a/gnu/packages/vpn.scm
+++ b/gnu/packages/vpn.scm
@@ -67,7 +67,7 @@ endpoints.")
                                 version ".tar.gz"))
             (sha256 (base32
                      "1128860lis89g1s21hqxvap2nq426c9j4bvgghncc1zj0ays7kj6"))
-            (patches (list (search-patch "vpnc-script.patch")))))
+            (patches (search-patches "vpnc-script.patch"))))
    (build-system gnu-build-system)
    (inputs `(("libgcrypt" ,libgcrypt)
              ("perl" ,perl)
diff --git a/gnu/packages/vtk.scm b/gnu/packages/vtk.scm
index 17312103dd..13ce2e2ac0 100644
--- a/gnu/packages/vtk.scm
+++ b/gnu/packages/vtk.scm
@@ -39,7 +39,7 @@
               (sha256
                (base32
                 "0d7shccdkyj4mbh2riilslgx3gd28in4c7xpm0lxa1ln8w5g2zdx"))
-              (patches (list (search-patch "vtk-mesa-10.patch")))))
+              (patches (search-patches "vtk-mesa-10.patch"))))
     (build-system cmake-build-system)
     (arguments
      ;; Build without '-g' to save space.
diff --git a/gnu/packages/w3m.scm b/gnu/packages/w3m.scm
index 45c9375def..42141fb04d 100644
--- a/gnu/packages/w3m.scm
+++ b/gnu/packages/w3m.scm
@@ -44,10 +44,10 @@
                "1qx9f0kprf92r1wxl3sacykla0g04qsi0idypzz24b7xy9ix5579"))
 
              ;; cf. https://bugs.archlinux.org/task/33397
-             (patches (list (search-patch "w3m-libgc.patch")
-                            (search-patch "w3m-force-ssl_verify_server-on.patch")
-                            (search-patch "w3m-disable-sslv2-and-sslv3.patch")
-                            (search-patch "w3m-disable-weak-ciphers.patch")))))
+             (patches (search-patches "w3m-libgc.patch"
+                                      "w3m-force-ssl_verify_server-on.patch"
+                                      "w3m-disable-sslv2-and-sslv3.patch"
+                                      "w3m-disable-weak-ciphers.patch"))))
     (build-system gnu-build-system)
     (arguments `(#:tests? #f  ; no check target
                  #:phases (alist-cons-before
diff --git a/gnu/packages/web.scm b/gnu/packages/web.scm
index 1f13474e95..a0e1ec9422 100644
--- a/gnu/packages/web.scm
+++ b/gnu/packages/web.scm
@@ -3,13 +3,14 @@
 ;;; Copyright © 2013 Aljosha Papsch <misc@rpapsch.de>
 ;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
 ;;; Copyright © 2015, 2016 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2015 Eric Dvorsak <eric@dvorsak.fr>
 ;;; Copyright © 2016 Sou Bunnbu <iyzsong@gmail.com>
 ;;; Copyright © 2016 Jelle Licht <jlicht@fsfe.org>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Rene Saavedra <rennes@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -35,6 +36,7 @@
   #:use-module (guix cvs-download)
   #:use-module (guix utils)
   #:use-module (guix build-system gnu)
+  #:use-module (guix build-system glib-or-gtk)
   #:use-module (guix build-system perl)
   #:use-module (guix build-system cmake)
   #:use-module (guix build-system r)
@@ -49,6 +51,8 @@
   #:use-module (gnu packages mit-krb5)
   #:use-module (gnu packages gd)
   #:use-module (gnu packages gettext)
+  #:use-module (gnu packages glib)
+  #:use-module (gnu packages gnome)
   #:use-module (gnu packages icu4c)
   #:use-module (gnu packages lua)
   #:use-module (gnu packages base)
@@ -402,7 +406,7 @@ UTS#46.")
               (sha256
                (base32
                 "14dsnmirjcrvwsffqp3as70qr6bbfaig2fv3zvs5g7005jrsbvpb"))
-              (patches (list (search-patch "tidy-CVE-2015-5522+5523.patch")))))
+              (patches (search-patches "tidy-CVE-2015-5522+5523.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases (alist-cons-after
@@ -605,8 +609,8 @@ from streaming URLs.  It is a command-line wrapper for the libquvi library.")
                            version ".tar.bz2"))
        (sha256
         (base32 "14155g48gamcv5s0828bzij6vr14nqmbndwq8j8f9g6vcph0nl70"))
-       (patches (map search-patch '("serf-comment-style-fix.patch"
-                                    "serf-deflate-buckets-test-fix.patch")))
+       (patches (search-patches "serf-comment-style-fix.patch"
+                                "serf-deflate-buckets-test-fix.patch"))
        (patch-flags '("-p0"))))
     (build-system gnu-build-system)
     (native-inputs
@@ -1718,8 +1722,8 @@ which can be used to parse directory listings.")
       (sha256
        (base32
         "1b6pbh7f76fb5sa4f0lhx085xy55pprz5v7z7li7pqiyw7i4f4bf"))
-      (patches (list
-                (search-patch "perl-finance-quote-unuse-mozilla-ca.patch")))))
+      (patches (search-patches
+                "perl-finance-quote-unuse-mozilla-ca.patch"))))
    (build-system perl-build-system)
    (propagated-inputs
     `(("perl-cgi" ,perl-cgi)
@@ -2288,9 +2292,8 @@ and IPv6 sockets, intended as a replacement for IO::Socket::INET.")
               (sha256
                (base32
                 "1mph52lw6x5v44wf8mw00llzi8pp6k5c4jnrnrvlacrlfv260jb8"))
-              (patches
-               (list
-                (search-patch "perl-io-socket-ssl-openssl-1.0.2f-fix.patch")))))
+              (patches (search-patches
+                        "perl-io-socket-ssl-openssl-1.0.2f-fix.patch"))))
     (build-system perl-build-system)
     (propagated-inputs `(("perl-net-ssleay" ,perl-net-ssleay)))
     (synopsis "Nearly transparent SSL encapsulation for IO::Socket::INET")
@@ -2418,8 +2421,8 @@ and retry a few times.")
        (sha256
         (base32
          "10dcsq4s2kc9cb1vccx17r187c81drirc3s1hbxh3rb8489kg2b2"))
-       (patches (list
-                 (search-patch "perl-net-amazon-s3-moose-warning.patch")))))
+       (patches (search-patches
+                 "perl-net-amazon-s3-moose-warning.patch"))))
     (build-system perl-build-system)
     (native-inputs
      `(("perl-libwww" ,perl-libwww)
@@ -2961,13 +2964,13 @@ particularly easy to create complete web applications using httpuv alone.")
 (define-public r-jsonlite
   (package
     (name "r-jsonlite")
-    (version "0.9.17")
+    (version "0.9.19")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "jsonlite" version))
               (sha256
                (base32
-                "07s11m8z43dh5pyci5rpjqj5js69q8prjar42qhhxbvdmcrjk4z7"))))
+                "1hbdraj3xv2l2gs9f205j8z054ycy0bfdvwdhvpa9qlji588sz7g"))))
     (build-system r-build-system)
     (home-page "http://arxiv.org/abs/1403.2805")
     (synopsis "Robust, high performance JSON parser and generator for R")
@@ -2985,13 +2988,13 @@ in systems and applications.")
 (define-public r-servr
   (package
     (name "r-servr")
-    (version "0.2")
+    (version "0.4")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "servr" version))
               (sha256
                (base32
-                "0gah99snaj8lk5zfzbxi3jwvpnlff9diz9gqv4qalfxpmb7fp6lc"))))
+                "1fkqf5ynd1g0932qwv5nr70bw42m8vxpc9rhi0qxmdamwqcw8qjn"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-httpuv" ,r-httpuv)
@@ -3010,16 +3013,17 @@ directory.")
 (define-public r-htmltools
   (package
     (name "r-htmltools")
-    (version "0.2.6")
+    (version "0.3.5")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "htmltools" version))
               (sha256
                (base32
-                "1gp6f6388xy3cvnb08q08vraidjp740gfxlafdd19m2s04v5hncz"))))
+                "0j9bf80grd6gwh7116m575pycv87c0wcwkxsz3gzzfs4aw3pxyr9"))))
     (build-system r-build-system)
     (propagated-inputs
-     `(("r-digest" ,r-digest)))
+     `(("r-digest" ,r-digest)
+       ("r-rcpp" ,r-rcpp)))
     (home-page "http://cran.r-project.org/web/packages/htmltools")
     (synopsis "R tools for HTML")
     (description
@@ -3029,13 +3033,13 @@ directory.")
 (define-public r-htmlwidgets
   (package
     (name "r-htmlwidgets")
-    (version "0.5")
+    (version "0.6")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "htmlwidgets" version))
               (sha256
                (base32
-                "1d583kk7g29r4sq0y1scri7fs48z6q17c051nyjywcvnpy4lvi8j"))))
+                "1sljs7zajzj1lsrrvqv7anpma4plzs79mqwmw7b2c5d7mn9py8lw"))))
     (build-system r-build-system)
     (propagated-inputs
      `(("r-htmltools" ,r-htmltools)
@@ -3052,13 +3056,13 @@ applications.")
 (define-public r-curl
   (package
     (name "r-curl")
-    (version "0.9.3")
+    (version "0.9.7")
     (source (origin
               (method url-fetch)
               (uri (cran-uri "curl" version))
               (sha256
                (base32
-                "02p9s1jlk8dcbvn71ivn4xnrqh9dwqyhgn4s1fzcfmnmfxhl5gld"))))
+                "1p24bcaf1wbfdi1r9ibyyp0l0zp4kzs4g3srv8vikz93hycm1qa6"))))
     (build-system r-build-system)
     (inputs
      `(("libcurl" ,curl)))
@@ -3208,3 +3212,41 @@ mangle the data format that you have into the one that you want with very
 little effort, and the program to do so is often shorter and simpler than
 you'd expect.")
     (license (list l:expat l:cc-by3.0))))
+
+(define-public uhttpmock
+  (package
+    (name "uhttpmock")
+    (version "0.5.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "http://tecnocode.co.uk/downloads/uhttpmock/"
+                           name "-" version ".tar.xz"))
+       (sha256
+        (base32
+         "0vniyx341pnnmvxmqacc49k0g7h9a9nhknfslidrqmxj5lm1ini6"))))
+    (build-system glib-or-gtk-build-system)
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-before 'check 'use-empty-ssl-cert-file
+           (lambda _
+             ;; Search for ca-certificates.crt files
+             ;; during the check phase.
+             (setenv "SSL_CERT_FILE" "/dev/null")
+             #t)))))
+    (native-inputs
+     `(("gobject-introspection" ,gobject-introspection)
+       ;; For check phase.
+       ("glib-networking" ,glib-networking)
+       ("gsettings-desktop-schemas" ,gsettings-desktop-schemas)
+       ("pkg-config" ,pkg-config)))
+    (inputs
+     `(("libsoup" ,libsoup)))
+    (home-page "https://gitlab.com/groups/uhttpmock")
+    (synopsis "Library for mocking web service APIs which use HTTP or HTTPS")
+    (description
+     "Uhttpmock is a project for mocking web service APIs which use HTTP or
+HTTPS.  It provides a library, libuhttpmock, which implements recording and
+playback of HTTP request/response traces.")
+    (license l:lgpl2.1+)))
diff --git a/gnu/packages/webkit.scm b/gnu/packages/webkit.scm
index 473d2e7cdc..734e4fc0df 100644
--- a/gnu/packages/webkit.scm
+++ b/gnu/packages/webkit.scm
@@ -53,14 +53,14 @@
 (define-public webkitgtk
   (package
     (name "webkitgtk")
-    (version "2.12.0")
+    (version "2.12.2")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://www.webkitgtk.org/releases/"
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
-                "19jyvyw8ss4bacq3f7ybdb0r16r84q12j2bpciyj9jqvzpw091m6"))))
+                "097i53ip93qfy8sgpv5qjf8fmi07gwm41q83jxrxldqwif89pi4x"))))
     (build-system cmake-build-system)
     (arguments
      '(#:tests? #f ; no tests
@@ -136,14 +136,14 @@ HTML/CSS applications to full-fledged web browsers.")
 (define-public webkitgtk-2.4
   (package (inherit webkitgtk)
     (name "webkitgtk")
-    (version "2.4.10")
+    (version "2.4.11")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://www.webkitgtk.org/releases/"
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
-                "0566yx5lxi40g0wpvmwbc8y76akd7zph7flrjdp2vv3z1nra9z9k"))))
+                "1xsvnvyvlywwyf6m9ainpsg87jkxjmd37q6zgz9cxb7v3c2ym2jq"))))
     (build-system gnu-build-system)
     (arguments
      '(#:tests? #f ; no tests
diff --git a/gnu/packages/wicd.scm b/gnu/packages/wicd.scm
index 350baf7373..f9aa657e56 100644
--- a/gnu/packages/wicd.scm
+++ b/gnu/packages/wicd.scm
@@ -46,11 +46,11 @@
                            "/+download/wicd-" version ".tar.gz"))
        (sha256
         (base32 "0qpbwwsrqdp40mm3a8djpn2d055rxxspdhwijwsdnws700a9d637"))
-       (patches (map search-patch
-                     '("wicd-bitrate-none-fix.patch"
-                       "wicd-get-selected-profile-fix.patch"
-                       "wicd-urwid-1.3.patch"
-                       "wicd-wpa2-ttls.patch")))))
+       (patches (search-patches
+                 "wicd-bitrate-none-fix.patch"
+                 "wicd-get-selected-profile-fix.patch"
+                 "wicd-urwid-1.3.patch"
+                 "wicd-wpa2-ttls.patch"))))
     (build-system python-build-system)
     (native-inputs `(("gettext" ,gnu-gettext)))
     (inputs `(("dbus-glib" ,dbus-glib)
diff --git a/gnu/packages/wm.scm b/gnu/packages/wm.scm
index a63e597599..60842efab2 100644
--- a/gnu/packages/wm.scm
+++ b/gnu/packages/wm.scm
@@ -286,7 +286,7 @@ tiling window manager for X.")
        (sha256
         (base32
          "0ak0yajzk3v4dg5wmaghv6acf7v02a4iw8qxmq5yw5ard8lrqn3r"))
-       (patches (map search-patch '("evilwm-lost-focus-bug.patch")))))
+       (patches (search-patches "evilwm-lost-focus-bug.patch"))))
     (build-system gnu-build-system)
     (inputs
      `(("libx11" ,libx11)
diff --git a/gnu/packages/wxwidgets.scm b/gnu/packages/wxwidgets.scm
index b49fb2fe84..2c4a26aeac 100644
--- a/gnu/packages/wxwidgets.scm
+++ b/gnu/packages/wxwidgets.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -31,6 +32,7 @@
   #:use-module (gnu packages image)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages sdl)
+  #:use-module (gnu packages webkit)
   #:use-module (gnu packages xorg))
 
 (define-public wxwidgets
@@ -45,7 +47,6 @@
        (sha256
         (base32 "0paq27brw4lv8kspxh9iklpa415mxi8zc117vbbbhfjgapf7js1l"))))
     (build-system glib-or-gtk-build-system)
-    ;; TODO: add WebKit
     (inputs
      `(("glu" ,glu)
        ;; XXX gstreamer-0.10 builds fail
@@ -56,12 +57,17 @@
        ("libsm" ,libsm)
        ("libtiff" ,libtiff)
        ("mesa" ,mesa)
+       ("webkitgtk" ,webkitgtk-2.4)
        ("sdl" ,sdl)))
     (native-inputs
      `(("pkg-config" ,pkg-config)))
     (arguments
      '(#:configure-flags
-       '("--with-regex=sys" "--with-libmspack" "--with-sdl")
+       '("--with-regex=sys" "--with-libmspack"
+         "--with-sdl"
+         "--enable-webview"
+         "--enable-webkit"
+         "--enable-webviewwebkit")
        #:make-flags
        (list (string-append "LDFLAGS=-Wl,-rpath="
                             (assoc-ref %outputs "out") "/lib"))
diff --git a/gnu/packages/xdisorg.scm b/gnu/packages/xdisorg.scm
index 7cb4f44ace..67bca6d894 100644
--- a/gnu/packages/xdisorg.scm
+++ b/gnu/packages/xdisorg.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2013, 2014 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
-;;; Copyright © 2014, 2015 Alex Kost <alezost@gmail.com>
+;;; Copyright © 2014, 2015, 2016 Alex Kost <alezost@gmail.com>
 ;;; Copyright © 2013, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Mathieu Lirzin <mthl@openmailbox.org>
 ;;; Copyright © 2015 Alexander I.Grafov <grafov@gmail.com>
@@ -32,21 +32,25 @@
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix utils)
+  #:use-module (guix build-system cmake)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system glib-or-gtk)
   #:use-module (guix build-system python)
   #:use-module (gnu packages)
   #:use-module (gnu packages asciidoc)
+  #:use-module (gnu packages algebra)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages image)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages gettext)
+  #:use-module (gnu packages gl)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gnome)               ;for libgudev
   #:use-module (gnu packages ncurses)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages python)
   #:use-module (gnu packages linux)
+  #:use-module (gnu packages gl)
   #:use-module (gnu packages guile)
   #:use-module (gnu packages xml)
   #:use-module (gnu packages gtk)
@@ -131,7 +135,7 @@ avoiding password prompts when X11 forwarding has already been setup.")
         (sha256
           (base32
            "1lcngsw33fy9my21rdiz1gs474bfdqcfxjrnfggbx4aypn1nhcp8"))
-        (patches (list (search-patch "xdotool-fix-makefile.patch")))))
+        (patches (search-patches "xdotool-fix-makefile.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:tests? #f ; Test suite requires a lot of black magic
@@ -229,7 +233,7 @@ rasterisation.")
         (sha256
           (base32
             "1gnf206zs8dwszvkv4z2hbvh23045z0q29kms127bqrv27hp2nzf"))
-        (patches (list (search-patch "libdrm-symbol-check.patch")))))
+        (patches (search-patches "libdrm-symbol-check.patch"))))
     (build-system gnu-build-system)
     (inputs
       `(("libpciaccess" ,libpciaccess)
@@ -311,7 +315,7 @@ System style license, and has no special dependencies.")
               (sha256
                (base32
                 "1afclc57b9017a73mfs9w7lbdvdipmf9q0xdk116f61gnvyix2np"))
-              (patches (list (search-patch "wmctrl-64-fix.patch")))))
+              (patches (search-patches "wmctrl-64-fix.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags
@@ -376,6 +380,80 @@ of the screen selected by mouse.")
     (license (license:x11-style "file://COPYING"
                                 "See 'COPYING' in the distribution."))))
 
+(define-public slop
+  (package
+    (name "slop")
+    (version "4.3.21")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/naelstrof/slop/archive/v"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0z0p4a3p5mc6fjh5f8js9ppb0maxyvfxpiw2n6nqc5nim1kv6bim"))))
+    (build-system cmake-build-system)
+    (arguments '(#:tests? #f))  ; no "check" target
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxrandr" ,libxrandr)
+       ("libxext" ,libxext)
+       ("imlib2" ,imlib2)
+       ("glew" ,glew)
+       ("mesa" ,mesa)))
+    (home-page "https://github.com/naelstrof/slop")
+    (synopsis "Select a region and print its bounds to stdout")
+    (description
+     "slop (Select Operation) is a tool that queries for a selection from a
+user and prints the region to stdout.  It grabs the mouse and turns it into a
+crosshair, lets the user click and drag to make a selection (or click on a
+window) while drawing a pretty box around it, then finally prints the
+selection's dimensions to stdout.")
+    (license license:gpl3+)))
+
+(define-public maim
+  (package
+    (name "maim")
+    (version "3.4.47")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/naelstrof/maim/archive/v"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0kfp7k55bxc5h6h0wv8bwmsc5ny66h9ra2z4dzs4yzszq16544pv"))))
+    (build-system cmake-build-system)
+    (arguments
+     '(#:tests? #f              ; no "check" target
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'patch-source
+           (lambda* (#:key inputs #:allow-other-keys)
+             (let ((slop (string-append (assoc-ref inputs "slop")
+                                        "/bin/slop")))
+               ;; "slop" command is hardcoded in the source; replace it
+               ;; with the full file name.
+               (substitute* "src/main.cpp"
+                 (("^( +slopcommand.*)\"slop\"" all front)
+                  (string-append front "\"" slop "\"")))))))))
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxrandr" ,libxrandr)
+       ("libxfixes" ,libxfixes)
+       ("imlib2" ,imlib2)
+       ("slop" ,slop)))
+    (home-page "https://github.com/naelstrof/maim")
+    (synopsis "Screenshot utility for X Window System")
+    (description
+     "maim (Make Image) is a tool that takes screenshots of your desktop and
+saves it in any format.  Along with a full screen, it allows you to capture a
+predefined region or a particular window.  Also, it makes it possible to
+include cursor in the resulting image.")
+    (license license:gpl3+)))
+
 (define-public unclutter
   (package
     (name "unclutter")
@@ -714,6 +792,7 @@ the X.Org X Server version 1.7 and later (X11R7.5 or later).")
        ("libx11" ,libx11)
        ("libxcb" ,libxcb)
        ("libxxf86vm" ,libxxf86vm)
+       ("libjpeg" ,libjpeg)
        ("glib" ,glib)))                           ;for Geoclue2 support
     (home-page "https://github.com/jonls/redshift")
     (synopsis "Adjust the color temperature of your screen")
@@ -724,3 +803,69 @@ twilight and early morning, the color temperature transitions smoothly from
 night to daytime temperature to allow your eyes to slowly adapt.  At night the
 color temperature should be set to match the lamps in your room.")
     (license license:gpl3+)))
+
+(define-public xscreensaver
+  (package
+    (name "xscreensaver")
+    (version "5.34")
+    (source
+     (origin
+       (method url-fetch)
+       (uri
+        (string-append "https://www.jwz.org/xscreensaver/xscreensaver-"
+                       version ".tar.gz"))
+       (sha256
+        (base32
+         "09sy5v8bn62hiq4ib3jyvp8lipqcvn3rdsj74q25qgklpv27xzvg"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f  ; no check target
+       #:phases
+       (modify-phases %standard-phases
+         (add-before 'configure 'adjust-gtk-resource-paths
+           (lambda _
+             (substitute* '("driver/Makefile.in" "po/Makefile.in.in")
+               (("@GTK_DATADIR@") "@datadir@")
+               (("@PO_DATADIR@") "@datadir@")))))
+       #:configure-flags '("--with-pam" "--with-proc-interrupts"
+                           "--without-readdisplay")
+       #:make-flags (list (string-append "AD_DIR="
+                                         (assoc-ref %outputs "out")
+                                         "/usr/lib/X11/app-defaults"))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("intltool" ,intltool)))
+    (inputs
+     `(("libx11" ,libx11)
+       ("libxext" ,libxext)
+       ("libxi" ,libxi)
+       ("libxt" ,libxt)
+       ("libxft" ,libxft)
+       ("libxmu" ,libxmu)
+       ("libxpm" ,libxpm)
+       ("libglade" ,libglade)
+       ("libxml2" ,libxml2)
+       ("libsm" ,libsm)
+       ("libjpeg" ,libjpeg)
+       ("linux-pam" ,linux-pam)
+       ("pango" ,pango)
+       ("gtk+" ,gtk+)
+       ("perl" ,perl)
+       ("cairo" ,cairo)
+       ("bc" ,bc)
+       ("libxrandr" ,libxrandr)
+       ("glu" ,glu)
+       ("glib" ,glib)))
+    (home-page "https://www.jwz.org/xscreensaver/")
+    (synopsis "Classic screen saver suite supporting screen locking")
+    (description
+     "xscreensaver is a popular screen saver collection with many entertaining
+demos.  It also acts as a nice screen locker.")
+    ;; xscreensaver doesn't have a single copyright file and instead relies on
+    ;; source comment headers, though most files have the same lax
+    ;; permissions.  To reduce complexity, we're pointing at Debian's
+    ;; breakdown of the copyright information.
+    (license (license:non-copyleft
+              (string-append
+               "http://metadata.ftp-master.debian.org/changelogs/"
+               "/main/x/xscreensaver/xscreensaver_5.34-2_copyright")))))
diff --git a/gnu/packages/xfce.scm b/gnu/packages/xfce.scm
index 03b49a86ac..c164c66a18 100644
--- a/gnu/packages/xfce.scm
+++ b/gnu/packages/xfce.scm
@@ -3,6 +3,7 @@
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2016 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2016 Florian Paul Schmidt <mista.tapas@gmx.net>
+;;; Copyright © 2016 Kei Yamashita <kei@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -272,7 +273,7 @@ management D-Bus specification.")
               (sha256
                (base32
                 "1c4p3ckghvsad1sj5v8wmar5mh9cbhail9mmhad2f9pwwb10z4ih"))
-              (patches (list (search-patch "xfce4-panel-plugins.patch")))))
+              (patches (search-patches "xfce4-panel-plugins.patch"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags '("--enable-gtk3")))
@@ -467,7 +468,7 @@ your system in categories, so you can quickly find and launch them.")
                 "01kvbd09c06j20n155hracsgrq06rlmfgdywffjsvlwpn19m9j38"))
               (patches
                ;; See: https://bugzilla.xfce.org/show_bug.cgi?id=12282
-               (list (search-patch "xfce4-session-fix-xflock4.patch")))
+               (search-patches "xfce4-session-fix-xflock4.patch"))
               (modules '((guix build utils)))
               (snippet
                '(begin
@@ -510,8 +511,7 @@ allows you to shutdown the computer from Xfce.")
               (sha256
                (base32
                 "108za1cmjslwzkdl76x9kwxkq8z734kg9nz8rxk057f10pqwxgh4"))
-              (patches
-               (list (search-patch "xfce4-settings-defaults.patch")))))
+              (patches (search-patches "xfce4-settings-defaults.patch"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
@@ -699,6 +699,7 @@ on your desktop.")
        ("gnome-icon-theme"     ,gnome-icon-theme)
        ("gtk-xfce-engine"      ,gtk-xfce-engine)
        ("hicolor-icon-theme"   ,hicolor-icon-theme)
+       ("ristretto"            ,ristretto)
        ("shared-mime-info"     ,shared-mime-info)
        ("thunar"               ,thunar)
        ("thunar-volman"        ,thunar-volman)
@@ -757,3 +758,60 @@ freedesktop-compliant DBus interfaces to inform other applications about current
 power level so that they can adjust their power consumption, and it provides the
 inhibit interface which allows applications to prevent automatic sleep.")
     (license gpl2+)))
+
+(define-public ristretto
+  (package
+    (name "ristretto")
+    (version "0.8.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://archive.xfce.org/src/apps/ristretto/"
+                                  (version-major+minor version) "/"
+                                  name "-" version ".tar.bz2"))
+              (sha256
+               (base32
+                "0a7kwhx51fd2kqh7l7kp13wcn39d2fjkwnn9rfd1k9ydrqj56qki"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)))
+    (inputs
+     `(("desktop-file-utils" ,desktop-file-utils)
+       ("libexif" ,libexif)
+       ("libxfce4ui" ,libxfce4ui)
+       ("librsvg" ,librsvg)
+       ("tumbler" ,tumbler)))
+    (home-page "http://docs.xfce.org/apps/ristretto/start")
+    (synopsis "Fast and lightweight picture-viewer")
+    (description
+     "The Ristretto Image Viewer is an application that can be used to view,
+and scroll through images.  It can be used to run a slideshow of images, open
+images with other applications like an image-editor or configure an image as
+the desktop wallpaper.")
+    (license gpl2+)))
+
+(define-public xfce4-taskmanager
+  (package
+    (name "xfce4-taskmanager")
+    (version "1.1.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://archive.xfce.org/src/apps/"
+                                  name "/" (version-major+minor version) "/"
+                                  name "-" version ".tar.bz2"))
+              (sha256
+               (base32
+                "1jwywmkkkmz7406m1jq40w6apiav25cznafhigbgpjv6z5hv27if"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)))
+    (inputs
+     `(("libwnck" ,libwnck-2)
+       ("gtk+" ,gtk+-2)))
+    (home-page "http://goodies.xfce.org/projects/applications/xfce4-taskmanager")
+    (synopsis "Easy to use task manager")
+    (description
+     "This is a task manager for the Xfce desktop.  It displays the CPU and
+memory usage graphically, and it can display processes as a tree.")
+    (license gpl2+)))
diff --git a/gnu/packages/xiph.scm b/gnu/packages/xiph.scm
index 1e157a4c96..244f0c84b4 100644
--- a/gnu/packages/xiph.scm
+++ b/gnu/packages/xiph.scm
@@ -111,7 +111,7 @@ polyphonic) audio and music at fixed and variable bitrates from 16 to
              (sha256
               (base32
                "0q8wark9ribij57dciym5vdikg2464p8q2mgqvfb78ksjh4s8vgk"))
-             (patches (list (search-patch "libtheora-config-guess.patch")))))
+             (patches (search-patches "libtheora-config-guess.patch"))))
     (build-system gnu-build-system)
     (inputs `(("libvorbis" ,libvorbis)))
     ;; The .pc files refer to libogg.
@@ -176,23 +176,26 @@ stereo encoding, and voice activity detection.")
      "Libao is a cross-platform audio library that allows programs to
 output audio using a simple API on a wide variety of platforms.
 It currently supports:
-Null output (handy for testing without a sound device),
-WAV files,
-AU files,
-RAW files,
-OSS (Open Sound System, used on Linux and FreeBSD),
-ALSA (Advanced Linux Sound Architecture),
-aRts (Analog RealTime Synth, used by KDE),
-PulseAudio (next generation GNOME sound server),
-esd (EsounD or Enlightened Sound Daemon),
-Mac OS X,
-Windows (98 and later),
-AIX,
-Sun/NetBSD/OpenBSD,
-IRIX,
-NAS (Network Audio Server),
-RoarAudio (Modern, multi-OS, networked Sound System),
-OpenBSD's sndio.")
+@enumerate
+@item Null output (handy for testing without a sound device),
+@item WAV files,
+@item AU files,
+@item RAW files,
+@item OSS (Open Sound System, used on Linux and FreeBSD),
+@item ALSA (Advanced Linux Sound Architecture),
+@item aRts (Analog RealTime Synth, used by KDE),
+@item PulseAudio (next generation GNOME sound server),
+@item esd (EsounD or Enlightened Sound Daemon),
+@item Mac OS X,
+@item Windows (98 and later),
+@item AIX,
+@item Sun/NetBSD/OpenBSD,
+@item IRIX,
+@item NAS (Network Audio Server),
+@item RoarAudio (Modern, multi-OS, networked Sound System),
+@item OpenBSD's sndio.
+@end enumerate
+")
     (license license:gpl2+)
     (home-page "http://www.xiph.org/ao/")))
 
@@ -267,7 +270,7 @@ Kate stream.")
             (sha256
              (base32
               "1g12bnh5ah08v529y72kfdz5lhvy75iaz7f9jskyby23m9dkk2d3"))
-            (patches (list (search-patch "vorbis-tools-CVE-2015-6749.patch")))))
+            (patches (search-patches "vorbis-tools-CVE-2015-6749.patch"))))
    (build-system gnu-build-system)
    (inputs `(("ao" ,ao)
              ("curl" ,curl)
diff --git a/gnu/packages/xml.scm b/gnu/packages/xml.scm
index f6a3f82063..838ce34364 100644
--- a/gnu/packages/xml.scm
+++ b/gnu/packages/xml.scm
@@ -131,7 +131,7 @@ project (but it is usable outside of the Gnome platform).")
              (sha256
               (base32
                "13029baw9kkyjgr7q3jccw2mz38amq7mmpr5p3bh775qawd1bisz"))
-             (patches (list (search-patch "libxslt-CVE-2015-7995.patch")))))
+             (patches (search-patches "libxslt-CVE-2015-7995.patch"))))
     (build-system gnu-build-system)
     (home-page "http://xmlsoft.org/XSLT/index.html")
     (synopsis "C library for applying XSLT stylesheets to XML documents")
@@ -653,7 +653,7 @@ UTF-8 and UTF-16 encoding.")
               (sha256
                (base32
                 "14smciid19lvkxqznfig77jxn5s4iq3jpb47vh5a6zcaqp7gvg8m"))
-              (patches (list (search-patch "tinyxml-use-stl.patch")))))
+              (patches (search-patches "tinyxml-use-stl.patch"))))
     (build-system gnu-build-system)
     ;; This library is missing *a lot* of the steps to make it usable, so we
     ;; have to add them here, like every other distro must do.
diff --git a/gnu/packages/xorg.scm b/gnu/packages/xorg.scm
index 4cf466883b..fd933e36a7 100644
--- a/gnu/packages/xorg.scm
+++ b/gnu/packages/xorg.scm
@@ -1514,7 +1514,7 @@ treat it as part of their software base when porting.")
             "0dn694mk56x6hdk6y9ylx4f128h5jcin278gnw2gb807rf3ygc1h"))
         ;; See https://bugs.freedesktop.org/show_bug.cgi?id=47792;
         ;; should become obsolete with the next release.
-        (patches (list (search-patch "luit-posix.patch")))))
+        (patches (search-patches "luit-posix.patch"))))
     (build-system gnu-build-system)
     (inputs
       `(("libfontenc" ,libfontenc)))
@@ -2577,7 +2577,7 @@ as USB mice.")
         (sha256
           (base32
            "07p5vdsj2ckxb6wh02s61akcv4qfg6s1d5ld3jn3lfaayd3f1466"))
-        (patches (list (search-patch "xf86-video-ark-remove-mibstore.patch")))))
+        (patches (search-patches "xf86-video-ark-remove-mibstore.patch"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -2603,7 +2603,7 @@ as USB mice.")
 ;;         (sha256
 ;;           (base32
 ;;            "1q64z8qqa0ix3cymqiwk1s3sphd1fvvz30lvyxhgkgciygz6dm69"))
-;;         (patches (list (search-patch "xf86-video-ast-remove-mibstore.patch")))))
+;;         (patches (search-patches "xf86-video-ast-remove-mibstore.patch"))))
 ;;     (build-system gnu-build-system)
 ;;     (inputs `(("xorg-server" ,xorg-server)))
 ;;     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -2711,7 +2711,7 @@ framebuffer device.")
         (sha256
           (base32
            "1s59kdj573v38sb14xfhp1l926aypbhy11vaz36y72x6calfkv6n"))
-        (patches (list (search-patch "xf86-video-geode-glibc-2.20.patch")))))
+        (patches (search-patches "xf86-video-geode-glibc-2.20.patch"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -2770,8 +2770,7 @@ compositing.  Both support Xv overlay and dynamic rotation with XRandR.")
         (sha256
           (base32
            "08a2aark2yn9irws9c78d9q44dichr03i9zbk61jgr54ncxqhzv5"))
-        (patches (list
-                  (search-patch "xf86-video-glint-remove-mibstore.patch")))))
+        (patches (search-patches "xf86-video-glint-remove-mibstore.patch"))))
     (build-system gnu-build-system)
     (inputs `(("xf86dgaproto" ,xf86dgaproto)
               ("xorg-server" ,xorg-server)))
@@ -2798,8 +2797,7 @@ X server.")
         (sha256
           (base32
            "171b8lbxr56w3isph947dnw7x87hc46v6m3mcxdcz44gk167x0pq"))
-        (patches (list
-                  (search-patch "xf86-video-i128-remove-mibstore.patch")))))
+        (patches (search-patches "xf86-video-i128-remove-mibstore.patch"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -2870,7 +2868,7 @@ It supports a variety of Intel graphics chipsets.")
         (sha256
           (base32
            "07xlf5nsjm0x18ij5gyy4lf8hwpl10i8chi3skpqjh84drdri61y"))
-        (patches (list (search-patch "xf86-video-mach64-glibc-2.20.patch")))))
+        (patches (search-patches "xf86-video-mach64-glibc-2.20.patch"))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
               ("xf86driproto" ,xf86driproto)
@@ -3005,7 +3003,7 @@ kernel mode setting (KMS).")
         (sha256
           (base32
            "1gqh1khc4zalip5hh2nksgs7i3piqq18nncgmsx9qvzi05azd5c3"))
-        (patches (list (search-patch "xf86-video-nv-remove-mibstore.patch")))))
+        (patches (search-patches "xf86-video-nv-remove-mibstore.patch"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -3057,8 +3055,7 @@ graphics cards.")
         (sha256
           (base32
            "1v8j4i1r268n4fc5gq54zg1x50j0rhw71f3lba7411mcblg2z7p4"))
-        (patches (list
-                  (search-patch "xf86-video-openchrome-glibc-2.20.patch")))))
+        (patches (search-patches "xf86-video-openchrome-glibc-2.20.patch"))))
     (build-system gnu-build-system)
     (inputs `(("libx11" ,libx11)
               ("libxext" ,libxext)
@@ -3272,7 +3269,7 @@ This driver supports SiS chipsets of 300/315/330/340 series.")
         (sha256
           (base32
            "0cb161lvdgi6qnf1sfz722qn38q7kgakcvj7b45ba3i0020828r0"))
-        (patches (list (search-patch "xf86-video-tga-remove-mibstore.patch")))))
+        (patches (search-patches "xf86-video-tga-remove-mibstore.patch"))))
     (build-system gnu-build-system)
     (inputs `(("xf86dgaproto" ,xf86dgaproto)
               ("xorg-server" ,xorg-server)))
@@ -3887,7 +3884,7 @@ protocol.")
         (sha256
           (base32
             "0y649an3jqfq9klkp9y5gj20xb78fw6g193f5mnzpl0hbz6fbc5p"))
-        (patches (list (search-patch "xmodmap-asprintf.patch")))))
+        (patches (search-patches "xmodmap-asprintf.patch"))))
     (build-system gnu-build-system)
     (inputs
       `(("xproto" ,xproto)
diff --git a/gnu/packages/zip.scm b/gnu/packages/zip.scm
index b7bed0e86d..6defbda49e 100644
--- a/gnu/packages/zip.scm
+++ b/gnu/packages/zip.scm
@@ -81,19 +81,19 @@ Compression ratios of 2:1 to 3:1 are common for text files.")
       (sha256
        (base32
         "0dxx11knh3nk95p2gg2ak777dd11pr7jx5das2g49l262scrcv83"))
-      (patches (map search-patch '("unzip-CVE-2014-8139.patch"
-                                   "unzip-CVE-2014-8140.patch"
-                                   "unzip-CVE-2014-8141.patch"
-                                   "unzip-CVE-2014-9636.patch"
-                                   "unzip-CVE-2015-7696.patch"
-                                   "unzip-CVE-2015-7697.patch"
-                                   "unzip-allow-greater-hostver-values.patch"
-                                   "unzip-initialize-symlink-flag.patch"
-                                   "unzip-remove-build-date.patch"
-                                   "unzip-attribs-overflow.patch"
-                                   "unzip-overflow-on-invalid-input.patch"
-                                   "unzip-format-secure.patch"
-                                   "unzip-overflow-long-fsize.patch")))))
+      (patches (search-patches "unzip-CVE-2014-8139.patch"
+                               "unzip-CVE-2014-8140.patch"
+                               "unzip-CVE-2014-8141.patch"
+                               "unzip-CVE-2014-9636.patch"
+                               "unzip-CVE-2015-7696.patch"
+                               "unzip-CVE-2015-7697.patch"
+                               "unzip-allow-greater-hostver-values.patch"
+                               "unzip-initialize-symlink-flag.patch"
+                               "unzip-remove-build-date.patch"
+                               "unzip-attribs-overflow.patch"
+                               "unzip-overflow-on-invalid-input.patch"
+                               "unzip-format-secure.patch"
+                               "unzip-overflow-long-fsize.patch"))))
     (build-system gnu-build-system)
     ;; no inputs; bzip2 is not supported, since not compiled with BZ_NO_STDIO
     (arguments