summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark H Weaver <mhw@netris.org>2016-02-27 08:52:23 -0500
committerMark H Weaver <mhw@netris.org>2016-02-27 08:52:23 -0500
commit048ec1a8b092a87de08bfe410be65642522b63ed (patch)
tree1279c4fa3fd09805dbfe06be3514879aa38d503e
parentfe5f687284889eeff3c1b73edab0aa26e58c3bc5 (diff)
parentb35461748b20d0172744974b39e7d9d033400c51 (diff)
downloadguix-048ec1a8b092a87de08bfe410be65642522b63ed.tar.gz
Merge branch 'master' into core-updates
-rw-r--r--Makefile.am3
-rw-r--r--doc.am1
-rw-r--r--doc/contributing.texi6
-rw-r--r--doc/emacs.texi11
-rw-r--r--doc/guix.texi901
-rw-r--r--doc/htmlxref.cnf652
-rw-r--r--emacs/guix-base.el27
-rw-r--r--emacs/guix-buffer.el4
-rw-r--r--emacs/guix-build-log.el3
-rw-r--r--emacs/guix-devel.el3
-rw-r--r--emacs/guix-init.el3
-rw-r--r--emacs/guix-main.scm4
-rw-r--r--emacs/guix-profiles.el8
-rw-r--r--emacs/guix-ui-package.el59
-rw-r--r--gnu-system.am38
-rw-r--r--gnu/build/linux-modules.scm20
-rw-r--r--gnu/build/vm.scm19
-rw-r--r--gnu/packages.scm69
-rw-r--r--gnu/packages/abduco.scm7
-rw-r--r--gnu/packages/admin.scm79
-rw-r--r--gnu/packages/adns.scm6
-rw-r--r--gnu/packages/aidc.scm14
-rw-r--r--gnu/packages/algebra.scm4
-rw-r--r--gnu/packages/audio.scm46
-rw-r--r--gnu/packages/augeas.scm59
-rw-r--r--gnu/packages/base.scm9
-rw-r--r--gnu/packages/bioinformatics.scm274
-rw-r--r--gnu/packages/bittorrent.scm6
-rw-r--r--gnu/packages/compression.scm2
-rw-r--r--gnu/packages/cpio.scm3
-rw-r--r--gnu/packages/curl.scm11
-rw-r--r--gnu/packages/databases.scm34
-rw-r--r--gnu/packages/dav.scm4
-rw-r--r--gnu/packages/dictionaries.scm5
-rw-r--r--gnu/packages/docker.scm1
-rw-r--r--gnu/packages/dvtm.scm7
-rw-r--r--gnu/packages/ebook.scm4
-rw-r--r--gnu/packages/emacs.scm120
-rw-r--r--gnu/packages/engineering.scm68
-rw-r--r--gnu/packages/feh.scm5
-rw-r--r--gnu/packages/finance.scm7
-rw-r--r--gnu/packages/fonts.scm9
-rw-r--r--gnu/packages/fontutils.scm37
-rw-r--r--gnu/packages/freedesktop.scm31
-rw-r--r--gnu/packages/fribidi.scm5
-rw-r--r--gnu/packages/games.scm32
-rw-r--r--gnu/packages/gcc.scm4
-rw-r--r--gnu/packages/gdb.scm6
-rw-r--r--gnu/packages/ghostscript.scm2
-rw-r--r--gnu/packages/gl.scm4
-rw-r--r--gnu/packages/glib.scm4
-rw-r--r--gnu/packages/gnome.scm185
-rw-r--r--gnu/packages/gnunet.scm43
-rw-r--r--gnu/packages/gnupg.scm11
-rw-r--r--gnu/packages/gnuzilla.scm9
-rw-r--r--gnu/packages/gps.scm19
-rw-r--r--gnu/packages/gstreamer.scm134
-rw-r--r--gnu/packages/gtk.scm27
-rw-r--r--gnu/packages/guile.scm64
-rw-r--r--gnu/packages/icu4c.scm11
-rw-r--r--gnu/packages/kde-frameworks.scm23
-rw-r--r--gnu/packages/kde.scm229
-rw-r--r--gnu/packages/ldc.scm45
-rw-r--r--gnu/packages/libcanberra.scm2
-rw-r--r--gnu/packages/linux.scm84
-rw-r--r--gnu/packages/lsh.scm57
-rw-r--r--gnu/packages/lua.scm2
-rw-r--r--gnu/packages/lxqt.scm9
-rw-r--r--gnu/packages/mail.scm42
-rw-r--r--gnu/packages/mate.scm211
-rw-r--r--gnu/packages/maths.scm10
-rw-r--r--gnu/packages/mit-krb5.scm70
-rw-r--r--gnu/packages/moe.scm5
-rw-r--r--gnu/packages/mpd.scm23
-rw-r--r--gnu/packages/music.scm156
-rw-r--r--gnu/packages/nano.scm4
-rw-r--r--gnu/packages/nettle.scm28
-rw-r--r--gnu/packages/ocaml.scm57
-rw-r--r--gnu/packages/openbox.scm7
-rw-r--r--gnu/packages/openstack.scm20
-rw-r--r--gnu/packages/owncloud.scm6
-rw-r--r--gnu/packages/package-management.scm51
-rw-r--r--gnu/packages/parallel.scm90
-rw-r--r--gnu/packages/patches/cpio-CVE-2016-2037.patch49
-rw-r--r--gnu/packages/patches/glibc-CVE-2015-7547.patch559
-rw-r--r--gnu/packages/patches/gnupg-simple-query-ignore-status-messages.patch142
-rw-r--r--gnu/packages/patches/icecat-update-graphite2.patch9988
-rw-r--r--gnu/packages/patches/libsndfile-CVE-2014-9496.patch55
-rw-r--r--gnu/packages/patches/libsndfile-CVE-2015-7805.patch95
-rw-r--r--gnu/packages/patches/libssh-0.6.5-CVE-2016-0739.patch77
-rw-r--r--gnu/packages/patches/libssh-CVE-2014-0017.patch89
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-2695-pt1.patch569
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-2695-pt2.patch65
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-2696.patch736
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-2697.patch55
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-2698-pt1.patch43
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-2698-pt2.patch132
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-8629.patch51
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-8630.patch81
-rw-r--r--gnu/packages/patches/mit-krb5-CVE-2015-8631.patch576
-rw-r--r--gnu/packages/patches/mit-krb5-init-context-null-spnego.patch49
-rw-r--r--gnu/packages/patches/ocaml-findlib-make-install.patch20
-rw-r--r--gnu/packages/patches/python-paste-remove-timing-test.patch16
-rw-r--r--gnu/packages/patches/python-paste-remove-website-test.patch21
-rw-r--r--gnu/packages/patches/qemu-CVE-2015-8619.patch119
-rw-r--r--gnu/packages/patches/qemu-CVE-2016-1981.patch95
-rw-r--r--gnu/packages/patches/qemu-CVE-2016-2197.patch40
-rw-r--r--gnu/packages/patches/qemu-usb-ehci-oob-read.patch49
-rw-r--r--gnu/packages/patches/slurm-configure-remove-nonfree-contribs.patch43
-rw-r--r--gnu/packages/patches/tclxml-3.2-install.patch17
-rw-r--r--gnu/packages/patches/xf86-video-mga-glibc-2.20.patch17
-rw-r--r--gnu/packages/patches/xf86-video-r128-glibc-2.20.patch17
-rw-r--r--gnu/packages/patches/xf86-video-siliconmotion-remove-mibstore.patch16
-rw-r--r--gnu/packages/patches/xf86-video-sis-fix-exa-crash.patch45
-rw-r--r--gnu/packages/patches/xf86-video-sis-update-api.patch128
-rw-r--r--gnu/packages/patches/xf86-video-tdfx-remove-mibstore.patch26
-rw-r--r--gnu/packages/patches/xf86-video-trident-remove-mibstore.patch23
-rw-r--r--gnu/packages/patches/xf86-video-vmware-glibc-2.20.patch15
-rw-r--r--gnu/packages/pdf.scm2
-rw-r--r--gnu/packages/perl.scm29
-rw-r--r--gnu/packages/pkg-config.scm14
-rw-r--r--gnu/packages/polkit.scm9
-rw-r--r--gnu/packages/pulseaudio.scm20
-rw-r--r--gnu/packages/pumpio.scm1
-rw-r--r--gnu/packages/python.scm1029
-rw-r--r--gnu/packages/qemu.scm6
-rw-r--r--gnu/packages/qt.scm37
-rw-r--r--gnu/packages/rdf.scm31
-rw-r--r--gnu/packages/ruby.scm2
-rw-r--r--gnu/packages/scheme.scm8
-rw-r--r--gnu/packages/screen.scm2
-rw-r--r--gnu/packages/ssh.scm61
-rw-r--r--gnu/packages/statistics.scm23
-rw-r--r--gnu/packages/tcl.scm75
-rw-r--r--gnu/packages/texlive.scm76
-rw-r--r--gnu/packages/textutils.scm31
-rw-r--r--gnu/packages/tls.scm98
-rw-r--r--gnu/packages/version-control.scm8
-rw-r--r--gnu/packages/video.scm98
-rw-r--r--gnu/packages/vim.scm8
-rw-r--r--gnu/packages/wine.scm18
-rw-r--r--gnu/packages/xdisorg.scm28
-rw-r--r--gnu/packages/xfce.scm46
-rw-r--r--gnu/packages/xnee.scm2
-rw-r--r--gnu/packages/xorg.scm365
-rw-r--r--gnu/packages/yasm.scm5
-rw-r--r--gnu/packages/yubico.scm9
-rw-r--r--gnu/packages/zsh.scm8
-rw-r--r--gnu/services/databases.scm3
-rw-r--r--gnu/services/desktop.scm2
-rw-r--r--gnu/services/herd.scm8
-rw-r--r--gnu/services/xorg.scm45
-rw-r--r--gnu/system.scm32
-rw-r--r--gnu/system/install.scm8
-rw-r--r--gnu/system/locale.scm32
-rw-r--r--gnu/system/vm.scm10
-rw-r--r--guix/derivations.scm98
-rw-r--r--guix/download.scm29
-rw-r--r--guix/gexp.scm3
-rw-r--r--guix/gnu-maintenance.scm37
-rw-r--r--guix/grafts.scm146
-rw-r--r--guix/http-client.scm18
-rw-r--r--guix/import/gem.scm63
-rw-r--r--guix/import/github.scm198
-rw-r--r--guix/licenses.scm26
-rw-r--r--guix/packages.scm7
-rw-r--r--guix/profiles.scm10
-rw-r--r--guix/scripts/build.scm1
-rw-r--r--guix/scripts/environment.scm239
-rw-r--r--guix/scripts/package.scm12
-rw-r--r--guix/scripts/publish.scm31
-rw-r--r--guix/scripts/refresh.scm10
-rw-r--r--guix/scripts/system.scm23
-rw-r--r--guix/store.scm29
-rw-r--r--tests/derivations.scm34
-rw-r--r--tests/grafts.scm81
-rw-r--r--tests/guix-environment-container.sh2
-rw-r--r--tests/guix-environment.sh104
-rw-r--r--tests/packages.scm5
-rw-r--r--tests/publish.scm8
-rw-r--r--tests/store.scm26
181 files changed, 17894 insertions, 4227 deletions
diff --git a/Makefile.am b/Makefile.am
index 9beeb9d564..4c53779aaa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,7 @@ MODULES =					\
   guix/serialization.scm			\
   guix/nar.scm					\
   guix/derivations.scm				\
+  guix/grafts.scm				\
   guix/gnu-maintenance.scm			\
   guix/upstream.scm				\
   guix/licenses.scm				\
@@ -108,6 +109,7 @@ MODULES =					\
   guix/import/cran.scm				\
   guix/import/hackage.scm			\
   guix/import/elpa.scm   			\
+  guix/import/github.scm   			\
   guix/scripts.scm				\
   guix/scripts/download.scm			\
   guix/scripts/build.scm			\
@@ -220,6 +222,7 @@ SCM_TESTS =					\
   tests/substitute.scm				\
   tests/builders.scm				\
   tests/derivations.scm				\
+  tests/grafts.scm				\
   tests/ui.scm					\
   tests/records.scm				\
   tests/utils.scm				\
diff --git a/doc.am b/doc.am
index 67da8ff8e2..127029c1ca 100644
--- a/doc.am
+++ b/doc.am
@@ -35,6 +35,7 @@ DOT_VECTOR_GRAPHICS =				\
   $(DOT_FILES:%.dot=%.pdf)
 
 EXTRA_DIST +=					\
+  doc/htmlxref.cnf				\
   doc/contributing.texi				\
   doc/emacs.texi				\
   doc/fdl-1.3.texi				\
diff --git a/doc/contributing.texi b/doc/contributing.texi
index 54fb23a822..3dbd3dbba6 100644
--- a/doc/contributing.texi
+++ b/doc/contributing.texi
@@ -315,6 +315,6 @@ extensions---or to the operating system kernel---e.g., reliance on
 
 @end enumerate
 
-When posting a patch to the mailing list, use @samp{[PATCH] @dots{}} as a
-subject.  You may use your email client or the @command{git send-mail}
-command.
+When posting a patch to the mailing list, use @samp{[PATCH] @dots{}} as
+a subject.  You may use your email client or the @command{git
+send-email} command.
diff --git a/doc/emacs.texi b/doc/emacs.texi
index d46c17c4a0..27f5365caa 100644
--- a/doc/emacs.texi
+++ b/doc/emacs.texi
@@ -150,7 +150,13 @@ Commands for displaying packages:
 Display all/newest available packages.
 
 @item M-x guix-installed-packages
-Display all installed packages.
+@itemx M-x guix-installed-user-packages
+@itemx M-x guix-installed-system-packages
+Display installed packages.  As described above, @kbd{M-x
+guix-installed-packages} uses an arbitrary profile that you can specify,
+while the other commands display packages installed in 2 special
+profiles: @file{~/.guix-profile} and @file{/run/current-system/profile}
+(only on GuixSD).
 
 @item M-x guix-obsolete-packages
 Display obsolete packages (the packages that are installed in a profile
@@ -240,6 +246,9 @@ this:
 @kbd{M-x guix-edit guix} opens
 @file{~/src/guix/gnu/packages/package-management.scm} file.
 
+Also you can use @kbd{C-u} prefix argument to specify a directory just
+for the current @kbd{M-x guix-edit} command.
+
 
 @node Emacs General info
 @subsection General information
diff --git a/doc/guix.texi b/doc/guix.texi
index 80a1621b45..4c9a91b399 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -11,12 +11,13 @@
 
 @copying
 Copyright @copyright{} 2012, 2013, 2014, 2015, 2016 Ludovic Courtès@*
-Copyright @copyright{} 2013, 2014 Andreas Enge@*
+Copyright @copyright{} 2013, 2014, 2016 Andreas Enge@*
 Copyright @copyright{} 2013 Nikita Karetnikov@*
 Copyright @copyright{} 2015 Mathieu Lirzin@*
 Copyright @copyright{} 2014 Pierre-Antoine Rault@*
 Copyright @copyright{} 2015 Taylan Ulrich Bayırlı/Kammer@*
 Copyright @copyright{} 2015, 2016 Leo Famulari
+Copyright @copyright{} 2016 Ben Woodcroft
 
 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -247,7 +248,7 @@ returns an installed package.  As a pure function, its result depends
 solely on its inputs---for instance, it cannot refer to software or
 scripts that were not explicitly passed as inputs.  A build function
 always produces the same result when passed a given set of inputs.  It
-cannot alter the system's environment in
+cannot alter the environment of the running system in
 any way; for instance, it cannot create, modify, or delete files outside
 of its build and installation directories.  This is achieved by running
 build processes in isolated environments (or @dfn{containers}), where only their
@@ -256,13 +257,13 @@ explicit inputs are visible.
 @cindex store
 The result of package build functions is @dfn{cached} in the file
 system, in a special directory called @dfn{the store} (@pxref{The
-Store}).  Each package is installed in a directory of its own, in the
+Store}).  Each package is installed in a directory of its own in the
 store---by default under @file{/gnu/store}.  The directory name contains
 a hash of all the inputs used to build that package; thus, changing an
 input yields a different directory name.
 
-This approach is the foundation of Guix's salient features: support for
-transactional package upgrade and rollback, per-user installation, and
+This approach is the foundation for the salient features of Guix: support
+for transactional package upgrade and rollback, per-user installation, and
 garbage collection of packages (@pxref{Features}).
 
 Guix has a command-line interface, which allows users to build, install,
@@ -327,7 +328,7 @@ $ wget ftp://alpha.gnu.org/gnu/guix/guix-binary-@value{VERSION}.@var{system}.tar
 $ gpg --verify guix-binary-@value{VERSION}.@var{system}.tar.xz.sig
 @end example
 
-If that command fails because you don't have the required public key,
+If that command fails because you do not have the required public key,
 then run this command to import it:
 
 @example
@@ -377,19 +378,29 @@ Create the group and user accounts for build users as explained below
 (@pxref{Build Environment Setup}).
 
 @item
-Run the daemon:
+Run the daemon, and set it to automatically start on boot.
+
+If your host distro uses the systemd init system, this can be achieved
+with these commands:
 
 @example
-# ~root/.guix-profile/bin/guix-daemon --build-users-group=guixbuild
+# cp ~root/.guix-profile/lib/systemd/system/guix-daemon.service \
+        /etc/systemd/system/
+# systemctl start guix-daemon && systemctl enable guix-daemon
 @end example
 
-On hosts using the systemd init system, drop
-@file{~root/.guix-profile/lib/systemd/system/guix-daemon.service} in
-@file{/etc/systemd/system}.
+If your host distro uses the Upstart init system:
+
+@example
+# cp ~root/.guix-profile/lib/upstart/system/guix-daemon.conf /etc/init/
+# start guix-daemon
+@end example
 
-Likewise, on hosts using the Upstart init system, drop
-@file{~root/.guix-profile/lib/upstart/system/guix-daemon.conf} in
-@file{/etc/init}.
+Otherwise, you can still start the daemon manually with:
+
+@example
+# ~root/.guix-profile/bin/guix-daemon --build-users-group=guixbuild
+@end example
 
 @item
 Make the @command{guix} command available to other users on the machine,
@@ -425,16 +436,25 @@ authorize them:
 @end example
 @end enumerate
 
-And that's it!  For additional tips and tricks, @pxref{Application
-Setup}.
+This completes root-level install of Guix.  Each user will need to
+perform additional steps to make their Guix envionment ready for use,
+@pxref{Application Setup}.
 
-The @code{guix} package must remain available in @code{root}'s
-profile, or it would become subject to garbage collection---in which
-case you would find yourself badly handicapped by the lack of the
-@command{guix} command.
+You can confirm that Guix is working by installing a sample package into
+the root profile:
 
-The tarball in question can be (re)produced and verified simply by
-running the following command in the Guix source tree:
+@example
+# guix package -i hello
+@end example
+
+The @code{guix} package must remain available in @code{root}'s profile,
+or it would become subject to garbage collection---in which case you
+would find yourself badly handicapped by the lack of the @command{guix}
+command.  In other words, do not remove @code{guix} by running
+@code{guix package -r guix}.
+
+The binary installation tarball can be (re)produced and verified simply
+by running the following command in the Guix source tree:
 
 @example
 make guix-binary.@var{system}.tar.xz
@@ -546,7 +566,7 @@ goes through the daemon.  For instance, command-line tools such as
 daemon (@i{via} remote procedure calls) to instruct it what to do.
 
 The following sections explain how to prepare the build daemon's
-environment.  Also @ref{Substitutes}, for information on how to allow
+environment.  See also @ref{Substitutes}, for information on how to allow
 the daemon to download pre-built binaries.
 
 @menu
@@ -625,7 +645,7 @@ that appear in the chroot's @code{/dev} is fixed, most of these files
 can only be created if the host has them.};
 
 @item
-the @code{/proc} directory; it only shows the container's processes
+the @code{/proc} directory; it only shows the processes of the container
 since a separate PID name space is used;
 
 @item
@@ -645,7 +665,7 @@ a writable @file{/tmp} directory.
 
 You can influence the directory where the daemon stores build trees
 @i{via} the @code{TMPDIR} environment variable.  However, the build tree
-within the chroot is always @file{/tmp/guix-build-@var{name}.drv-0},
+within the chroot is always called @file{/tmp/guix-build-@var{name}.drv-0},
 where @var{name} is the derivation name---e.g., @code{coreutils-8.24}.
 This way, the value of @code{TMPDIR} does not leak inside build
 environments, which avoids discrepancies in cases where build processes
@@ -674,9 +694,9 @@ When desired, the build daemon can @dfn{offload}
 derivation builds to other machines
 running Guix, using the @code{offload} @dfn{build hook}.  When that
 feature is enabled, a list of user-specified build machines is read from
-@file{/etc/guix/machines.scm}; anytime a build is requested, for
+@file{/etc/guix/machines.scm}; every time a build is requested, for
 instance via @code{guix build}, the daemon attempts to offload it to one
-of the machines that satisfies the derivation's constraints, in
+of the machines that satisfy the constraints of the derivation, in
 particular its system type---e.g., @file{x86_64-linux}.  Missing
 prerequisites for the build are copied over SSH to the target machine,
 which then proceeds with the build; upon success the output(s) of the
@@ -715,16 +735,16 @@ Avahi in Guile Scheme Programs}).  The @code{build-machine} data type is
 detailed below.
 
 @deftp {Data Type} build-machine
-This data type represents build machines the daemon may offload builds
-to.  The important fields are:
+This data type represents build machines to which the daemon may offload
+builds.  The important fields are:
 
 @table @code
 
 @item name
-The remote machine's host name.
+The host name of the remote machine.
 
 @item system
-The remote machine's system type---e.g., @code{"x86_64-linux"}.
+The system type of the remote machine---e.g., @code{"x86_64-linux"}.
 
 @item user
 The user account to use when connecting to the remote machine over SSH.
@@ -738,7 +758,7 @@ A number of optional fields may be specified:
 @table @code
 
 @item port
-Port number of the machine's SSH server (default: 22).
+Port number of SSH server on the machine (default: 22).
 
 @item private-key
 The SSH private key file to use when connecting to the machine.
@@ -774,7 +794,7 @@ this is the case by running:
 lsh build-machine guile -c "'(use-modules (guix config))'"
 @end example
 
-There's one last thing to do once @file{machines.scm} is in place.  As
+There is one last thing to do once @file{machines.scm} is in place.  As
 explained above, when offloading, files are transferred back and forth
 between the machine stores.  For this to work, you first need to
 generate a key pair on each machine to allow the daemon to export signed
@@ -1022,8 +1042,8 @@ get everything in place.  Here are some of them.
 @cindex locales, when not on GuixSD
 @vindex LOCPATH
 @vindex GUIX_LOCPATH
-Packages installed @i{via} Guix will not use the host system's locale
-data.  Instead, you must first install one of the locale packages
+Packages installed @i{via} Guix will not use the locale data of the
+host system.  Instead, you must first install one of the locale packages
 available with Guix and then define the @code{GUIX_LOCPATH} environment
 variable:
 
@@ -1034,7 +1054,7 @@ $ export GUIX_LOCPATH=$HOME/.guix-profile/lib/locale
 
 Note that the @code{glibc-locales} package contains data for all the
 locales supported by the GNU@tie{}libc and weighs in at around
-110@tie{}MiB.  Alternately, the @code{glibc-utf8-locales} is smaller but
+110@tie{}MiB.  Alternatively, the @code{glibc-utf8-locales} is smaller but
 limited to a few UTF-8 locales.
 
 The @code{GUIX_LOCPATH} variable plays a role similar to @code{LOCPATH}
@@ -1043,9 +1063,9 @@ Manual}).  There are two important differences though:
 
 @enumerate
 @item
-@code{GUIX_LOCPATH} is honored only by Guix's libc, and not by the libc
+@code{GUIX_LOCPATH} is honored only by the libc in Guix, and not by the libc
 provided by foreign distros.  Thus, using @code{GUIX_LOCPATH} allows you
-to make sure the foreign distro's programs will not end up loading
+to make sure the programs of the foreign distro will not end up loading
 incompatible locale data.
 
 @item
@@ -1062,10 +1082,10 @@ versions may be incompatible.
 @subsection X11 Fonts
 
 The majority of graphical applications use Fontconfig to locate and
-load fonts and perform X11-client-side rendering.  Guix's
-@code{fontconfig} package looks for fonts in @file{$HOME/.guix-profile}
+load fonts and perform X11-client-side rendering.  The @code{fontconfig}
+package in Guix looks for fonts in @file{$HOME/.guix-profile}
 by default.  Thus, to allow graphical applications installed with Guix
-to display fonts, you will have to install fonts with Guix as well.
+to display fonts, you have to install fonts with Guix as well.
 Essential font packages include @code{gs-fonts}, @code{font-dejavu}, and
 @code{font-gnu-freefont-ttf}.
 
@@ -1094,9 +1114,9 @@ the Emacs package system organizes the file structure (@pxref{Package
 Files,,, emacs, The GNU Emacs Manual}).
 
 By default, Emacs (installed with Guix) ``knows'' where these packages
-are placed, so you don't need to perform any configuration.  If, for
+are placed, so you do not need to perform any configuration.  If, for
 some reason, you want to avoid auto-loading Emacs packages installed
-with Guix, you can do it by running Emacs with @code{--no-site-file}
+with Guix, you can do so by running Emacs with @code{--no-site-file}
 option (@pxref{Init File,,, emacs, The GNU Emacs Manual}).
 
 @c TODO What else?
@@ -1107,7 +1127,7 @@ option (@pxref{Init File,,, emacs, The GNU Emacs Manual}).
 
 The purpose of GNU Guix is to allow users to easily install, upgrade, and
 remove software packages, without having to know about their build
-procedure or dependencies.  Guix also goes beyond this obvious set of
+procedures or dependencies.  Guix also goes beyond this obvious set of
 features.
 
 This chapter describes the main features of Guix, as well as the package
@@ -1149,7 +1169,7 @@ simply continues to point to
 coexist on the same system without any interference.
 
 The @command{guix package} command is the central tool to manage
-packages (@pxref{Invoking guix package}).  It operates on those per-user
+packages (@pxref{Invoking guix package}).  It operates on the per-user
 profiles, and can be used @emph{with normal user privileges}.
 
 The command provides the obvious install, remove, and upgrade
@@ -1166,8 +1186,8 @@ of their profile, which was known to work well.  Similarly, the global
 system configuration is subject to transactional upgrades and roll-back
 (@pxref{Using the Configuration System}).
 
-All those packages in the package store may be @emph{garbage-collected}.
-Guix can determine which packages are still referenced by the user
+All packages in the package store may be @emph{garbage-collected}.
+Guix can determine which packages are still referenced by user
 profiles, and remove those that are provably no longer referenced
 (@pxref{Invoking guix gc}).  Users may also explicitly remove old
 generations of their profile so that the packages they refer to can be
@@ -1197,8 +1217,8 @@ otherwise, it builds the package from source, locally
 Control over the build environment is a feature that is also useful for
 developers.  The @command{guix environment} command allows developers of
 a package to quickly set up the right development environment for their
-package, without having to manually install the package's dependencies
-in their profile (@pxref{Invoking guix environment}).
+package, without having to manually install the dependencies of the
+package into their profile (@pxref{Invoking guix environment}).
 
 @node Invoking guix package
 @section Invoking @command{guix package}
@@ -1289,7 +1309,7 @@ An example is the GNU MPC library: its C header files refer to those of
 the GNU MPFR library, which in turn refer to those of the GMP library.
 Thus, when installing MPC, the MPFR and GMP libraries also get installed
 in the profile; removing MPC also removes MPFR and GMP---unless they had
-also been explicitly installed independently.
+also been explicitly installed by the user.
 
 Besides, packages sometimes rely on the definition of environment
 variables for their search paths (see explanation of
@@ -1327,7 +1347,7 @@ As an example, @var{file} might contain a definition like this
 @end example
 
 Developers may find it useful to include such a @file{package.scm} file
-in the root of their project's source tree that can be used to test
+in the root of their project source tree that can be used to test
 development snapshots and create reproducible development environments
 (@pxref{Invoking guix environment}).
 
@@ -1398,11 +1418,11 @@ before any other actions.
 
 When rolling back from the first generation that actually contains
 installed packages, the profile is made to point to the @dfn{zeroth
-generation}, which contains no files apart from its own meta-data.
+generation}, which contains no files apart from its own metadata.
 
-Installing, removing, or upgrading packages from a generation that has
-been rolled back to overwrites previous future generations.  Thus, the
-history of a profile's generations is always linear.
+After having rolled back, installing, removing, or upgrading packages
+overwrites previous future generations.  Thus, the history of the
+generations in a profile is always linear.
 
 @item --switch-generation=@var{pattern}
 @itemx -S @var{pattern}
@@ -1465,8 +1485,8 @@ variable, even though, taken individually, neither @file{foo} nor
 Use @var{profile} instead of the user's default profile.
 
 @item --verbose
-Produce verbose output.  In particular, emit the environment's build log
-on the standard error port.
+Produce verbose output.  In particular, emit the build log of the
+environment on the standard error port.
 
 @item --bootstrap
 Use the bootstrap Guile to build the profile.  This option is only
@@ -1474,7 +1494,7 @@ useful to distribution developers.
 
 @end table
 
-In addition to these actions @command{guix package} supports the
+In addition to these actions, @command{guix package} supports the
 following options to query the current state of a profile, or the
 availability of packages:
 
@@ -1484,7 +1504,7 @@ availability of packages:
 @itemx -s @var{regexp}
 @cindex searching for packages
 List the available packages whose name, synopsis, or description matches
-@var{regexp}.  Print all the meta-data of matching packages in
+@var{regexp}.  Print all the metadata of matching packages in
 @code{recutils} format (@pxref{Top, GNU recutils databases,, recutils,
 GNU recutils manual}).
 
@@ -1610,7 +1630,7 @@ specified order.  Neither spaces nor trailing commas are allowed.
 
 @item @emph{Ranges}.  @code{--list-generations=2..9} prints the
 specified generations and everything in between.  Note that the start of
-a range must be lesser than its end.
+a range must be smaller than its end.
 
 It is also possible to omit the endpoint.  For example,
 @code{--list-generations=2..}, returns all generations starting from the
@@ -1636,17 +1656,17 @@ deletes generations that are more than one month old.
 If the current generation matches, it is @emph{not} deleted.  Also, the
 zeroth generation is never deleted.
 
-Note that deleting generations prevents roll-back to them.
+Note that deleting generations prevents rolling back to them.
 Consequently, this command must be used with care.
 
 @end table
 
 Finally, since @command{guix package} may actually start build
 processes, it supports all the common build options (@pxref{Common Build
-Options}).  It also support package transformation options, such as
+Options}).  It also supports package transformation options, such as
 @option{--with-source} (@pxref{Package Transformation Options}).
 However, note that package transformations are lost when upgrading; to
-preserve transformation across upgrades, you should define your own
+preserve transformations across upgrades, you should define your own
 package variant in a Guile module and add it to @code{GUIX_PACKAGE_PATH}
 (@pxref{Defining Packages}).
 
@@ -1781,7 +1801,7 @@ like to discuss this project, join us on @email{guix-devel@@gnu.org}.
 @cindex package outputs
 
 Often, packages defined in Guix have a single @dfn{output}---i.e., the
-source package leads exactly one directory in the store.  When running
+source package leads to exactly one directory in the store.  When running
 @command{guix package -i glibc}, one installs the default output of the
 GNU libc package; the default output is called @code{out}, but its name
 can be omitted as shown in this command.  In this particular case, the
@@ -1808,7 +1828,7 @@ guix package -i glib:doc
 @end example
 
 Some packages install programs with different ``dependency footprints''.
-For instance, the WordNet package install both command-line tools and
+For instance, the WordNet package installs both command-line tools and
 graphical user interfaces (GUIs).  The former depend solely on the C
 library, whereas the latter depend on Tcl/Tk and the underlying X
 libraries.  In this case, we leave the command-line tools in the default
@@ -1830,7 +1850,7 @@ guix package}).
 @section Invoking @command{guix gc}
 
 @cindex garbage collector
-Packages that are installed but not used may be @dfn{garbage-collected}.
+Packages that are installed, but not used, may be @dfn{garbage-collected}.
 The @command{guix gc} command allows users to explicitly run the garbage
 collector to reclaim space from the @file{/gnu/store} directory.  It is
 the @emph{only} way to remove files from @file{/gnu/store}---removing
@@ -1914,8 +1934,8 @@ include the store files themselves, their references, and the references
 of these, recursively.  In other words, the returned list is the
 @dfn{transitive closure} of the store files.
 
-@xref{Invoking guix size}, for a tool to profile the size of an
-element's closure.  @xref{Invoking guix graph}, for a tool to visualize
+@xref{Invoking guix size}, for a tool to profile the size of the closure
+of an element.  @xref{Invoking guix graph}, for a tool to visualize
 the graph of references.
 
 @end table
@@ -1931,13 +1951,13 @@ store and to control disk usage.
 Verify the integrity of the store.
 
 By default, make sure that all the store items marked as valid in the
-daemon's database actually exist in @file{/gnu/store}.
+database of the daemon actually exist in @file{/gnu/store}.
 
-When provided, @var{options} must a comma-separated list containing one
+When provided, @var{options} must be a comma-separated list containing one
 or more of @code{contents} and @code{repair}.
 
-When passing @option{--verify=contents}, the daemon will compute the
-content hash of each store item and compare it against its hash in the
+When passing @option{--verify=contents}, the daemon computse the
+content hash of each store item and compares it against its hash in the
 database.  Hash mismatches are reported as data corruptions.  Because it
 traverses @emph{all the files in the store}, this command can take a
 long time, especially on systems with a slow disk drive.
@@ -1975,9 +1995,15 @@ On completion, @command{guix package} will use packages and package
 versions from this just-retrieved copy of Guix.  Not only that, but all
 the Guix commands and Scheme modules will also be taken from that latest
 version.  New @command{guix} sub-commands added by the update also
-become available@footnote{Under the hood, @command{guix pull} updates
-the @file{~/.config/guix/latest} symbolic link to point to the latest
-Guix, and the @command{guix} command loads code from there.}.
+become available.
+
+Any user can update their Guix copy using @command{guix pull}, and the
+effect is limited to the user who run @command{guix pull}.  For
+instance, when user @code{root} runs @command{guix pull}, this has no
+effect on the version of Guix that user @code{alice} sees, and vice
+versa@footnote{Under the hood, @command{guix pull} updates the
+@file{~/.config/guix/latest} symbolic link to point to the latest Guix,
+and the @command{guix} command loads code from there.}.
 
 The @command{guix pull} command is usually invoked with no arguments,
 but it supports the following options:
@@ -2004,8 +2030,30 @@ useful to Guix developers.
 The @command{guix archive} command allows users to @dfn{export} files
 from the store into a single archive, and to later @dfn{import} them.
 In particular, it allows store files to be transferred from one machine
-to another machine's store.  For example, to transfer the @code{emacs}
-package to a machine connected over SSH, one would run:
+to the store on another machine.
+
+To export store files as an archive to standard output, run:
+
+@example
+guix archive --export @var{options} @var{specifications}...
+@end example
+
+@var{specifications} may be either store file names or package
+specifications, as for @command{guix package} (@pxref{Invoking guix
+package}).  For instance, the following command creates an archive
+containing the @code{gui} output of the @code{git} package and the main
+output of @code{emacs}:
+
+@example
+guix archive --export git:gui /gnu/store/...-emacs-24.3 > great.nar
+@end example
+
+If the specified packages are not built yet, @command{guix archive}
+automatically builds them.  The build process may be controlled with the
+common build options (@pxref{Common Build Options}).
+
+To transfer the @code{emacs} package to a machine connected over SSH,
+one would run:
 
 @example
 guix archive --export -r emacs | ssh the-machine guix archive --import
@@ -2023,14 +2071,14 @@ guix archive --export -r $(readlink -f ~/.guix-profile) | \
 @noindent
 However, note that, in both examples, all of @code{emacs} and the
 profile as well as all of their dependencies are transferred (due to
-@code{-r}), regardless of what is already available in the target
-machine's store.  The @code{--missing} option can help figure out which
-items are missing from the target's store.
+@code{-r}), regardless of what is already available in the store on the
+target machine.  The @code{--missing} option can help figure out which
+items are missing from the target store.
 
 Archives are stored in the ``Nix archive'' or ``Nar'' format, which is
 comparable in spirit to `tar', but with a few noteworthy differences
 that make it more appropriate for our purposes.  First, rather than
-recording all Unix meta-data for each file, the Nar format only mentions
+recording all Unix metadata for each file, the Nar format only mentions
 the file type (regular, directory, or symbolic link); Unix permissions
 and owner/group are dismissed.  Second, the order in which directory
 entries are stored always follows the order of file names according to
@@ -2073,7 +2121,7 @@ the store.
 
 @item --generate-key[=@var{parameters}]
 @cindex signing, archives
-Generate a new key pair for the daemons.  This is a prerequisite before
+Generate a new key pair for the daemon.  This is a prerequisite before
 archives can be exported with @code{--export}.  Note that this operation
 usually takes time, because it needs to gather enough entropy to
 generate the key pair.
@@ -2083,7 +2131,7 @@ The generated key pair is typically stored under @file{/etc/guix}, in
 key, which must be kept secret.)  When @var{parameters} is omitted,
 an ECDSA key using the Ed25519 curve is generated, or, for Libgcrypt
 versions before 1.6.0, it is a 4096-bit RSA key.
-Alternately, @var{parameters} can specify
+Alternatively, @var{parameters} can specify
 @code{genkey} parameters suitable for Libgcrypt (@pxref{General
 public-key related Functions, @code{gcry_pk_genkey},, gcrypt, The
 Libgcrypt Reference Manual}).
@@ -2127,26 +2175,6 @@ archive contents coming from possibly untrusted substitute servers.
 
 @end table
 
-To export store files as an archive to the standard output, run:
-
-@example
-guix archive --export @var{options} @var{specifications}...
-@end example
-
-@var{specifications} may be either store file names or package
-specifications, as for @command{guix package} (@pxref{Invoking guix
-package}).  For instance, the following command creates an archive
-containing the @code{gui} output of the @code{git} package and the main
-output of @code{emacs}:
-
-@example
-guix archive --export git:gui /gnu/store/...-emacs-24.3 > great.nar
-@end example
-
-If the specified packages are not built yet, @command{guix archive}
-automatically builds them.  The build process may be controlled with the
-common build options (@pxref{Common Build Options}).
-
 @c *********************************************************************
 @include emacs.texi
 
@@ -2226,8 +2254,8 @@ package looks like this:
 
 @noindent
 Without being a Scheme expert, the reader may have guessed the meaning
-of the various fields here.  This expression binds variable @code{hello}
-to a @code{<package>} object, which is essentially a record
+of the various fields here.  This expression binds the variable
+@code{hello} to a @code{<package>} object, which is essentially a record
 (@pxref{SRFI-9, Scheme records,, guile, GNU Guile Reference Manual}).
 This package object can be inspected using procedures found in the
 @code{(guix packages)} module; for instance, @code{(package-name hello)}
@@ -2237,7 +2265,7 @@ With luck, you may be able to import part or all of the definition of
 the package you are interested in from another repository, using the
 @code{guix import} command (@pxref{Invoking guix import}).
 
-In the example above, @var{hello} is defined into a module of its own,
+In the example above, @var{hello} is defined in a module of its own,
 @code{(gnu packages hello)}.  Technically, this is not strictly
 necessary, but it is convenient to do so: all the packages defined in
 modules under @code{(gnu packages @dots{})} are automatically known to
@@ -2308,7 +2336,7 @@ more information on how to test package definitions, and
 @ref{Invoking guix lint}, for information on how to check a definition
 for style conformance.
 
-Eventually, updating the package definition to a new upstream version
+Finally, updating the package definition to a new upstream version
 can be partly automated by the @command{guix refresh} command
 (@pxref{Invoking guix refresh}).
 
@@ -2388,7 +2416,7 @@ tuples, where each tuple has a label for the input (a string) as its
 first element, a package, origin, or derivation as its second element,
 and optionally the name of the output thereof that should be used, which
 defaults to @code{"out"} (@pxref{Packages with Multiple Outputs}, for
-more on package outputs).  For example, the list below specifies 3
+more on package outputs).  For example, the list below specifies three
 inputs:
 
 @example
@@ -2404,15 +2432,15 @@ dependencies listed in @code{inputs} are built for the @emph{target}
 architecture; conversely, dependencies listed in @code{native-inputs}
 are built for the architecture of the @emph{build} machine.
 
-@code{native-inputs} is typically where you would list tools needed at
-build time but not at run time, such as Autoconf, Automake, pkg-config,
+@code{native-inputs} is typically used to list tools needed at
+build time, but not at run time, such as Autoconf, Automake, pkg-config,
 Gettext, or Bison.  @command{guix lint} can report likely mistakes in
 this area (@pxref{Invoking guix lint}).
 
 @anchor{package-propagated-inputs}
 Lastly, @code{propagated-inputs} is similar to @code{inputs}, but the
-specified packages will be force-installed alongside the package they
-belong to (@pxref{package-cmd-propagated-inputs, @command{guix
+specified packages will be automatically installed alongside the package
+they belong to (@pxref{package-cmd-propagated-inputs, @command{guix
 package}}, for information on how @command{guix package} deals with
 propagated inputs.)
 
@@ -2420,9 +2448,9 @@ For example this is necessary when a C/C++ library needs headers of
 another library to compile, or when a pkg-config file refers to another
 one @i{via} its @code{Requires} field.
 
-Another example where @code{propagated-inputs} is useful is for
-languages that lack a facility to record the run-time search path akin
-to ELF's @code{RUNPATH}; this includes Guile, Python, Perl, GHC, and
+Another example where @code{propagated-inputs} is useful is for languages
+that lack a facility to record the run-time search path akin to the
+@code{RUNPATH}of ELF files; this includes Guile, Python, Perl, GHC, and
 more.  To ensure that libraries written in those languages can find
 library code they depend on at run time, run-time dependencies must be
 listed in @code{propagated-inputs} rather than @code{inputs}.
@@ -2441,7 +2469,7 @@ A list of @code{search-path-specification} objects describing
 search-path environment variables honored by the package.
 
 @item @code{replacement} (default: @code{#f})
-This must either @code{#f} or a package object that will be used as a
+This must be either @code{#f} or a package object that will be used as a
 @dfn{replacement} for this package.  @xref{Security Updates, grafts},
 for details.
 
@@ -2452,7 +2480,8 @@ A one-line description of the package.
 A more elaborate description of the package.
 
 @item @code{license}
-The license of the package; a value from @code{(guix licenses)}.
+The license of the package; a value from @code{(guix licenses)},
+or a list of such values.
 
 @item @code{home-page}
 The URL to the home-page of the package, as a string.
@@ -2465,7 +2494,7 @@ The list of systems supported by the package, as strings of the form
 The list of maintainers of the package, as @code{maintainer} objects.
 
 @item @code{location} (default: source location of the @code{package} form)
-The source location of the package.  It's useful to override this when
+The source location of the package.  It is useful to override this when
 inheriting from another package, in which case this field is not
 automatically corrected.
 @end table
@@ -2489,13 +2518,13 @@ the @code{method} (see below).  For example, when using the
 values are: a URL represented as a string, or a list thereof.
 
 @item @code{method}
-A procedure that will handle the URI.
+A procedure that handles the URI.
 
 Examples include:
 
 @table @asis
 @item @var{url-fetch} from @code{(guix download)}
-download a file the HTTP, HTTPS, or FTP URL specified in the
+download a file from the HTTP, HTTPS, or FTP URL specified in the
 @code{uri} field;
 
 @item @var{git-fetch} from @code{(guix git-download)}
@@ -2519,7 +2548,7 @@ base-32 string.
 The file name under which the source code should be saved.  When this is
 @code{#f}, a sensible default value will be used in most cases.  In case
 the source is fetched from a URL, the file name from the URL will be
-used.  For version control checkouts, it's recommended to provide the
+used.  For version control checkouts, it is recommended to provide the
 file name explicitly because the default is not very descriptive.
 
 @item @code{patches} (default: @code{'()})
@@ -2559,7 +2588,7 @@ this is @code{#f}, a sensible default is used.
 @cindex build system
 Each package definition specifies a @dfn{build system} and arguments for
 that build system (@pxref{Defining Packages}).  This @code{build-system}
-field represents the build procedure of the package, as well implicit
+field represents the build procedure of the package, as well as implicit
 dependencies of that build procedure.
 
 Build systems are @code{<build-system>} objects.  The interface to
@@ -2583,7 +2612,7 @@ evaluated in the @dfn{build stratum}---i.e., by a Guile process launched
 by the daemon (@pxref{Derivations}).
 
 The main build system is @var{gnu-build-system}, which implements the
-standard build procedure for GNU packages and many other packages.  It
+standard build procedure for GNU and many other packages.  It
 is provided by the @code{(guix build-system gnu)} module.
 
 @defvr {Scheme Variable} gnu-build-system
@@ -2592,7 +2621,7 @@ thereof (@pxref{Configuration, configuration and makefile conventions,,
 standards, GNU Coding Standards}).
 
 @cindex build phases
-In a nutshell, packages using it configured, built, and installed with
+In a nutshell, packages using it are configured, built, and installed with
 the usual @code{./configure && make && make check && make install}
 command sequence.  In practice, a few additional steps are often needed.
 All these steps are split up in separate @dfn{phases},
@@ -2648,7 +2677,7 @@ The list of phases used for a particular package can be changed with the
 @code{#:phases} parameter.  For instance, passing:
 
 @example
-#:phases (alist-delete 'configure %standard-phases)
+#:phases (modify-phases %standard-phases (delete 'configure))
 @end example
 
 means that all the phases described above will be used, except the
@@ -2657,8 +2686,8 @@ means that all the phases described above will be used, except the
 In addition, this build system ensures that the ``standard'' environment
 for GNU packages is available.  This includes tools such as GCC, libc,
 Coreutils, Bash, Make, Diffutils, grep, and sed (see the @code{(guix
-build-system gnu)} module for a complete list.)  We call these the
-@dfn{implicit inputs} of a package, because package definitions don't
+build-system gnu)} module for a complete list).  We call these the
+@dfn{implicit inputs} of a package, because package definitions do not
 have to mention them.
 @end defvr
 
@@ -2694,8 +2723,8 @@ This build system adds the following two phases to the ones defined by
 
 @table @code
 @item glib-or-gtk-wrap
-The phase @code{glib-or-gtk-wrap} ensures that programs found under
-@file{bin/} are able to find GLib's ``schemas'' and
+The phase @code{glib-or-gtk-wrap} ensures that programs in
+@file{bin/} are able to find GLib ``schemas'' and
 @uref{https://developer.gnome.org/gtk3/stable/gtk-running.html, GTK+
 modules}.  This is achieved by wrapping the programs in launch scripts
 that appropriately set the @code{XDG_DATA_DIRS} and @code{GTK_PATH}
@@ -2709,9 +2738,9 @@ where wrapping would gratuitously add a dependency of that output on
 GLib and GTK+.
 
 @item glib-or-gtk-compile-schemas
-The phase @code{glib-or-gtk-compile-schemas} makes sure that all GLib's
+The phase @code{glib-or-gtk-compile-schemas} makes sure that all
 @uref{https://developer.gnome.org/gio/stable/glib-compile-schemas.html,
-GSettings schemas} are compiled.  Compilation is performed by the
+GSettings schemas} of GLib are compiled.  Compilation is performed by the
 @command{glib-compile-schemas} program.  It is provided by the package
 @code{glib:bin} which is automatically imported by the build system.
 The @code{glib} package providing @command{glib-compile-schemas} can be
@@ -2728,7 +2757,7 @@ packages, which consists in running @code{python setup.py build} and
 then @code{python setup.py install --prefix=/gnu/store/@dots{}}.
 
 For packages that install stand-alone Python programs under @code{bin/},
-it takes care of wrapping these programs so their @code{PYTHONPATH}
+it takes care of wrapping these programs so that their @code{PYTHONPATH}
 environment variable points to all the Python libraries they depend on.
 
 Which Python package is used can be specified with the @code{#:python}
@@ -2741,7 +2770,7 @@ implements the standard build procedure for Perl packages, which either
 consists in running @code{perl Build.PL --prefix=/gnu/store/@dots{}},
 followed by @code{Build} and @code{Build install}; or in running
 @code{perl Makefile.PL PREFIX=/gnu/store/@dots{}}, followed by
-@code{make} and @code{make install}; depending on which of
+@code{make} and @code{make install}, depending on which of
 @code{Build.PL} or @code{Makefile.PL} is present in the package
 distribution.  Preference is given to the former if both @code{Build.PL}
 and @code{Makefile.PL} exist in the package distribution.  This
@@ -2816,8 +2845,8 @@ parameter which defaults to @code{ghc}.
 
 @defvr {Scheme Variable} emacs-build-system
 This variable is exported by @code{(guix build-system emacs)}.  It
-implements an installation procedure similar to the one of Emacs' own
-packaging system (@pxref{Packages,,, emacs, The GNU Emacs Manual}).
+implements an installation procedure similar to the packaging system
+of Emacs itself (@pxref{Packages,,, emacs, The GNU Emacs Manual}).
 
 It first creates the @code{@var{package}-autoloads.el} file, then it
 byte compiles all Emacs Lisp files.  Differently from the Emacs
@@ -2836,7 +2865,7 @@ and does not have a notion of build phases.
 This variable is exported by @code{(guix build-system trivial)}.
 
 This build system requires a @code{#:builder} argument.  This argument
-must be a Scheme expression that builds the package's output(s)---as
+must be a Scheme expression that builds the package output(s)---as
 with @code{build-expression->derivation} (@pxref{Derivations,
 @code{build-expression->derivation}}).
 @end defvr
@@ -2847,8 +2876,8 @@ with @code{build-expression->derivation} (@pxref{Derivations,
 @cindex store
 @cindex store paths
 
-Conceptually, the @dfn{store} is where derivations that have been
-successfully built are stored---by default, under @file{/gnu/store}.
+Conceptually, the @dfn{store} is the place where derivations that have
+been built successfully are stored---by default, @file{/gnu/store}.
 Sub-directories in the store are referred to as @dfn{store paths}.  The
 store has an associated database that contains information such as the
 store paths referred to by each store path, and the list of @emph{valid}
@@ -2856,8 +2885,8 @@ store paths---paths that result from a successful build.
 
 The store is always accessed by the daemon on behalf of its clients
 (@pxref{Invoking guix-daemon}).  To manipulate the store, clients
-connect to the daemon over a Unix-domain socket, send it requests, and
-read the result---these are remote procedure calls, or RPCs.
+connect to the daemon over a Unix-domain socket, send requests to it,
+and read the result---these are remote procedure calls, or RPCs.
 
 The @code{(guix store)} module provides procedures to connect to the
 daemon, and to perform RPCs.  These are described below.
@@ -2866,7 +2895,7 @@ daemon, and to perform RPCs.  These are described below.
 Connect to the daemon over the Unix-domain socket at @var{file}.  When
 @var{reserve-space?} is true, instruct it to reserve a little bit of
 extra space on the file system so that the garbage collector can still
-operate, should the disk become full.  Return a server object.
+operate should the disk become full.  Return a server object.
 
 @var{file} defaults to @var{%default-socket-path}, which is the normal
 location given the options that were passed to @command{configure}.
@@ -2885,7 +2914,14 @@ Procedures that make RPCs all take a server object as their first
 argument.
 
 @deffn {Scheme Procedure} valid-path? @var{server} @var{path}
-Return @code{#t} when @var{path} is a valid store path.
+@cindex invalid store items
+Return @code{#t} when @var{path} designates a valid store item and
+@code{#f} otherwise (an invalid item may exist on disk but still be
+invalid, for instance because it is the result of an aborted or failed
+build.)
+
+A @code{&nix-protocol-error} condition is raised if @var{path} is not
+prefixed by the store directory (@file{/gnu/store}).
 @end deffn
 
 @deffn {Scheme Procedure} add-text-to-store @var{server} @var{name} @var{text} [@var{references}]
@@ -3155,9 +3191,9 @@ So, to exit the monad and get the desired effect, one must use
 @result{} /gnu/store/...-sh-symlink
 @end example
 
-Note that the @code{(guix monad-repl)} module extends Guile's REPL with
+Note that the @code{(guix monad-repl)} module extends the Guile REPL with
 new ``meta-commands'' to make it easier to deal with monadic procedures:
-@code{run-in-store}, and @code{enter-store-monad}.  The former, is used
+@code{run-in-store}, and @code{enter-store-monad}.  The former is used
 to ``run'' a single monadic value through the store:
 
 @example
@@ -3339,7 +3375,8 @@ monadic procedures:
 
 @deffn {Monadic Procedure} package-file @var{package} [@var{file}] @
        [#:system (%current-system)] [#:target #f] @
-       [#:output "out"] Return as a monadic
+       [#:output "out"]
+Return as a monadic
 value in the absolute file name of @var{file} within the @var{output}
 directory of @var{package}.  When @var{file} is omitted, return the name
 of the @var{output} directory of @var{package}.  When @var{target} is
@@ -3361,12 +3398,12 @@ Monadic version of @code{package-derivation} and
 @cindex build code quoting
 So we have ``derivations'', which represent a sequence of build actions
 to be performed to produce an item in the store (@pxref{Derivations}).
-Those build actions are performed when asking the daemon to actually
+These build actions are performed when asking the daemon to actually
 build the derivations; they are run by the daemon in a container
 (@pxref{Invoking guix-daemon}).
 
 @cindex strata of code
-It should come as no surprise that we like to write those build actions
+It should come as no surprise that we like to write these build actions
 in Scheme.  When we do that, we end up with two @dfn{strata} of Scheme
 code@footnote{The term @dfn{stratum} in this context was coined by
 Manuel Serrano et al.@: in the context of their work on Hop.  Oleg
@@ -3380,19 +3417,19 @@ performs build actions, such as making directories, invoking
 
 To describe a derivation and its build actions, one typically needs to
 embed build code inside host code.  It boils down to manipulating build
-code as data, and Scheme's homoiconicity---code has a direct
+code as data, and the homoiconicity of Scheme---code has a direct
 representation as data---comes in handy for that.  But we need more than
-Scheme's normal @code{quasiquote} mechanism to construct build
+the normal @code{quasiquote} mechanism in Scheme to construct build
 expressions.
 
 The @code{(guix gexp)} module implements @dfn{G-expressions}, a form of
 S-expressions adapted to build expressions.  G-expressions, or
-@dfn{gexps}, consist essentially in three syntactic forms: @code{gexp},
+@dfn{gexps}, consist essentially of three syntactic forms: @code{gexp},
 @code{ungexp}, and @code{ungexp-splicing} (or simply: @code{#~},
-@code{#$}, and @code{#$@@}), which are comparable respectively to
-@code{quasiquote}, @code{unquote}, and @code{unquote-splicing}
-(@pxref{Expression Syntax, @code{quasiquote},, guile, GNU Guile
-Reference Manual}).  However, there are major differences:
+@code{#$}, and @code{#$@@}), which are comparable to
+@code{quasiquote}, @code{unquote}, and @code{unquote-splicing},
+respectivel (@pxref{Expression Syntax, @code{quasiquote},, guile,
+GNU Guile Reference Manual}).  However, there are major differences:
 
 @itemize
 @item
@@ -3415,9 +3452,9 @@ This mechanism is not limited to package and derivation
 objects: @dfn{compilers} able to ``lower'' other high-level objects to
 derivations or files in the store can be defined,
 such that these objects can also be inserted
-into gexps.  For example, a useful type of high-level object that can be
+into gexps.  For example, a useful type of high-level objects that can be
 inserted in a gexp is ``file-like objects'', which make it easy to
-add files to the store and refer to them in
+add files to the store and to refer to them in
 derivations and such (see @code{local-file} and @code{plain-file}
 below.)
 
@@ -3444,8 +3481,8 @@ As one would expect, the @code{"/gnu/store/@dots{}-coreutils-8.22"} string is
 substituted to the reference to the @var{coreutils} package in the
 actual build code, and @var{coreutils} is automatically made an input to
 the derivation.  Likewise, @code{#$output} (equivalent to @code{(ungexp
-output)}) is replaced by a string containing the derivation's output
-directory name.
+output)}) is replaced by a string containing the directory name of the
+output of the derivation.
 
 @cindex cross compilation
 In a cross-compilation context, it is useful to distinguish between
@@ -3784,7 +3821,7 @@ The general syntax is:
 guix build @var{options} @var{package-or-derivation}@dots{}
 @end example
 
-As an example, the following command builds the latest version of Emacs
+As an example, the following command builds the latest versions of Emacs
 and of Guile, displays their build logs, and finally displays the
 resulting directories:
 
@@ -3890,7 +3927,7 @@ stashing one of the build results with @code{guix archive --export},
 then rebuilding, and finally comparing the two results.
 
 @item --no-build-hook
-Do not attempt to offload builds @i{via} the daemon's ``build hook''
+Do not attempt to offload builds @i{via} the ``build hook'' of the daemon
 (@pxref{Daemon Offload Setup}).  That is, always build things locally
 instead of offloading builds to remote machines.
 
@@ -3953,7 +3990,7 @@ the parsed command-line options.
 @cindex package variants
 Another set of command-line options supported by @command{guix build}
 and also @command{guix package} are @dfn{package transformation
-options}.  These are options that allow you to define @dfn{package
+options}.  These are options that make it possible to define @dfn{package
 variants}---for instance, packages built from different source code.
 This is a convenient way to create customized packages on the fly
 without having to type in the definitions of package variants
@@ -3966,11 +4003,11 @@ Use @var{source} as the source of the corresponding package.
 @var{source} must be a file name or a URL, as for @command{guix
 download} (@pxref{Invoking guix download}).
 
-The ``corresponding package'' is taken to be one specified on the
-command line whose name matches the base of @var{source}---e.g., if
-@var{source} is @code{/src/guile-2.0.10.tar.gz}, the corresponding
+The ``corresponding package'' is taken to be the one specified on the
+command line the name of which matches the base of @var{source}---e.g.,
+if @var{source} is @code{/src/guile-2.0.10.tar.gz}, the corresponding
 package is @code{guile}.  Likewise, the version string is inferred from
-@var{source}; in the previous example, it's @code{2.0.10}.
+@var{source}; in the previous example, it is @code{2.0.10}.
 
 This option allows users to try out versions of packages other than the
 one provided by the distribution.  The example below downloads
@@ -4001,7 +4038,7 @@ Replace dependency on @var{package} by a dependency on
 @var{replacement} must be a package specification such as @code{guile}
 or @code{guile@@1.8}.
 
-For instance, the following command builds Guix but replaces its
+For instance, the following command builds Guix, but replaces its
 dependency on the current stable version of Guile with a dependency on
 the development version of Guile, @code{guile-next}:
 
@@ -4045,7 +4082,7 @@ For example, @var{expr} may be @code{(@@ (gnu packages guile)
 guile-1.8)}, which unambiguously designates this specific variant of
 version 1.8 of Guile.
 
-Alternately, @var{expr} may be a G-expression, in which case it is used
+Alternatively, @var{expr} may be a G-expression, in which case it is used
 as a build program passed to @code{gexp->derivation}
 (@pxref{G-Expressions}).
 
@@ -4055,14 +4092,15 @@ monadic value, which is then passed through @code{run-with-store}.
 
 @item --source
 @itemx -S
-Build the packages' source derivations, rather than the packages
+Build the source derivations of the packages, rather than the packages
 themselves.
 
 For instance, @code{guix build -S gcc} returns something like
-@file{/gnu/store/@dots{}-gcc-4.7.2.tar.bz2}, which is GCC's source tarball.
+@file{/gnu/store/@dots{}-gcc-4.7.2.tar.bz2}, which is the GCC
+source tarball.
 
 The returned source tarball is the result of applying any patches and
-code snippets specified in the package's @code{origin} (@pxref{Defining
+code snippets specified in the package @code{origin} (@pxref{Defining
 Packages}).
 
 @item --sources
@@ -4079,8 +4117,8 @@ This value causes the @code{--sources} option to behave in the same way
 as the @code{--source} option.
 
 @item all
-Build all packages' source derivations, including any source that might
-be listed as @code{inputs}.  This is the default value.
+Build the source derivations of all packages, including any source that
+might be listed as @code{inputs}.  This is the default value.
 
 @example
 $ guix build --sources tzdata
@@ -4090,8 +4128,8 @@ The following derivations will be built:
 @end example
 
 @item transitive
-Build all packages' source derivations, as well as all source
-derivations for packages' transitive inputs.  This can be used e.g. to
+Build the source derivations of all packages, as well of all transitive
+inputs to the packages.  This can be used e.g. to
 prefetch package source for later offline building.
 
 @example
@@ -4111,7 +4149,7 @@ The following derivations will be built:
 @item --system=@var{system}
 @itemx -s @var{system}
 Attempt to build for @var{system}---e.g., @code{i686-linux}---instead of
-the host's system type.
+the system type of the build host.
 
 An example use of this is on Linux-based systems, which can emulate
 different personalities.  For instance, passing
@@ -4132,9 +4170,9 @@ Rebuild @var{package-or-derivation}, which are already available in the
 store, and raise an error if the build results are not bit-for-bit
 identical.
 
-This mechanism allows you to check whether previously-installed
-substitutes are genuine (@pxref{Substitutes}), or whether a package's
-build result is deterministic.  @xref{Invoking guix challenge}, for more
+This mechanism allows you to check whether previously installed
+substitutes are genuine (@pxref{Substitutes}), or whether the build result
+of a package is deterministic.  @xref{Invoking guix challenge}, for more
 background information and tools.
 
 @item --no-grafts
@@ -4154,7 +4192,7 @@ collector root.
 
 @item --log-file
 Return the build log file names or URLs for the given
-@var{package-or-derivation}s, or raise an error if build logs are
+@var{package-or-derivation}, or raise an error if build logs are
 missing.
 
 This works regardless of how packages or derivations are specified.  For
@@ -4171,8 +4209,8 @@ If a log is unavailable locally, and unless @code{--no-substitutes} is
 passed, the command looks for a corresponding log on one of the
 substitute servers (as specified with @code{--substitute-urls}.)
 
-So for instance, let's say you want to see the build log of GDB on MIPS
-but you're actually on an @code{x86_64} machine:
+So for instance, imagine you want to see the build log of GDB on MIPS,
+but you are actually on an @code{x86_64} machine:
 
 @example
 $ guix build --log-file gdb -s mips64el-linux 
@@ -4200,9 +4238,9 @@ launches the program specified in the @code{VISUAL} or in the
 @code{EDITOR} environment variable to edit the recipe of GCC@tie{}4.8.4
 and that of Vim.
 
-If you are using Emacs, note that the Emacs user interface provides
+If you are using Emacs, note that the Emacs user interface provides the
 @kbd{M-x guix-edit} command and a similar functionality in the ``package
-info'' and ``package list'' buffers created by @kbd{M-x
+info'' and ``package list'' buffers created by the @kbd{M-x
 guix-search-by-name} and similar commands (@pxref{Emacs Commands}).
 
 
@@ -4210,7 +4248,7 @@ guix-search-by-name} and similar commands (@pxref{Emacs Commands}).
 @section Invoking @command{guix download}
 
 When writing a package definition, developers typically need to download
-the package's source tarball, compute its SHA256 hash, and write that
+a source tarball, compute its SHA256 hash, and write that
 hash in the package definition (@pxref{Defining Packages}).  The
 @command{guix download} tool helps with this task: it downloads a file
 from the given URI, adds it to the store, and prints both its file name
@@ -4274,10 +4312,10 @@ in the definitions of packages.
 Compute the hash on @var{file} recursively.
 
 In this case, the hash is computed on an archive containing @var{file},
-including its children if it is a directory.  Some of @var{file}'s
-meta-data is part of the archive; for instance, when @var{file} is a
+including its children if it is a directory.  Some of the metadata of
+@var{file} is part of the archive; for instance, when @var{file} is a
 regular file, the hash is different depending on whether @var{file} is
-executable or not.  Meta-data such as time stamps has no impact on the
+executable or not.  Metadata such as time stamps has no impact on the
 hash (@pxref{Invoking guix archive}).
 @c FIXME: Replace xref above with xref to an ``Archive'' section when
 @c it exists.
@@ -4290,10 +4328,10 @@ hash (@pxref{Invoking guix archive}).
 @cindex importing packages
 @cindex package import
 @cindex package conversion
-The @command{guix import} command is useful for people willing to add a
-package to the distribution but who'd rather do as little work as
-possible to get there---a legitimate demand.  The command knows of a few
-repositories from which it can ``import'' package meta-data.  The result
+The @command{guix import} command is useful for people who would like to
+add a package to the distribution with as little work as
+possible---a legitimate demand.  The command knows of a few
+repositories from which it can ``import'' package metadata.  The result
 is a package definition, or a template thereof, in the format we know
 (@pxref{Defining Packages}).
 
@@ -4304,17 +4342,17 @@ guix import @var{importer} @var{options}@dots{}
 @end example
 
 @var{importer} specifies the source from which to import package
-meta-data, and @var{options} specifies a package identifier and other
+metadata, and @var{options} specifies a package identifier and other
 options specific to @var{importer}.  Currently, the available
 ``importers'' are:
 
 @table @code
 @item gnu
-Import meta-data for the given GNU package.  This provides a template
+Import metadata for the given GNU package.  This provides a template
 for the latest version of that GNU package, including the hash of its
 source tarball, and its canonical synopsis and description.
 
-Additional information such as the package's dependencies and its
+Additional information such as the package dependencies and its
 license needs to be figured out manually.
 
 For example, the following command returns a package definition for
@@ -4329,19 +4367,19 @@ Specific command-line options are:
 @table @code
 @item --key-download=@var{policy}
 As for @code{guix refresh}, specify the policy to handle missing OpenPGP
-keys when verifying the package's signature.  @xref{Invoking guix
+keys when verifying the package signature.  @xref{Invoking guix
 refresh, @code{--key-download}}.
 @end table
 
 @item pypi
 @cindex pypi
-Import meta-data from the @uref{https://pypi.python.org/, Python Package
+Import metadata from the @uref{https://pypi.python.org/, Python Package
 Index}@footnote{This functionality requires Guile-JSON to be installed.
 @xref{Requirements}.}.  Information is taken from the JSON-formatted
 description available at @code{pypi.python.org} and usually includes all
 the relevant information, including package dependencies.
 
-The command below imports meta-data for the @code{itsdangerous} Python
+The command below imports metadata for the @code{itsdangerous} Python
 package:
 
 @example
@@ -4350,18 +4388,18 @@ guix import pypi itsdangerous
 
 @item gem
 @cindex gem
-Import meta-data from @uref{https://rubygems.org/,
+Import metadata from @uref{https://rubygems.org/,
 RubyGems}@footnote{This functionality requires Guile-JSON to be
 installed.  @xref{Requirements}.}.  Information is taken from the
 JSON-formatted description available at @code{rubygems.org} and includes
 most relevant information, including runtime dependencies.  There are
-some caveats, however.  The meta-data doesn't distinguish between
+some caveats, however.  The metadata doesn't distinguish between
 synopses and descriptions, so the same string is used for both fields.
 Additionally, the details of non-Ruby dependencies required to build
 native extensions is unavailable and left as an exercise to the
 packager.
 
-The command below imports meta-data for the @code{rails} Ruby package:
+The command below imports metadata for the @code{rails} Ruby package:
 
 @example
 guix import gem rails
@@ -4369,15 +4407,17 @@ guix import gem rails
 
 @item cpan
 @cindex CPAN
-Import meta-data from @uref{https://www.metacpan.org/, MetaCPAN}.
-Information is taken from the JSON-formatted meta-data provided through
+Import metadata from @uref{https://www.metacpan.org/, MetaCPAN}@footnote{This
+functionality requires Guile-JSON to be installed.
+@xref{Requirements}.}.
+Information is taken from the JSON-formatted metadata provided through
 @uref{https://api.metacpan.org/, MetaCPAN's API} and includes most
 relevant information, such as module dependencies.  License information
 should be checked closely.  If Perl is available in the store, then the
 @code{corelist} utility will be used to filter core modules out of the
 list of dependencies.
 
-The command command below imports meta-data for the @code{Acme::Boolean}
+The command command below imports metadata for the @code{Acme::Boolean}
 Perl module:
 
 @example
@@ -4387,28 +4427,28 @@ guix import cpan Acme::Boolean
 @item cran
 @cindex CRAN
 @cindex Bioconductor
-Import meta-data from @uref{http://cran.r-project.org/, CRAN}, the
+Import metadata from @uref{http://cran.r-project.org/, CRAN}, the
 central repository for the @uref{http://r-project.org, GNU@tie{}R
 statistical and graphical environment}.
 
-Information is extracted from the package's @code{DESCRIPTION} file.
+Information is extracted from the @code{DESCRIPTION} file of the package.
 
-The command command below imports meta-data for the @code{Cairo}
+The command command below imports metadata for the @code{Cairo}
 R package:
 
 @example
 guix import cran Cairo
 @end example
 
-When @code{--archive=bioconductor} is added, meta-data is imported from
+When @code{--archive=bioconductor} is added, metadata is imported from
 @uref{http://www.bioconductor.org/, Bioconductor}, a repository of R
 packages for for the analysis and comprehension of high-throughput
 genomic data in bioinformatics.
 
-Information is extracted from a package's @code{DESCRIPTION} file
+Information is extracted from the @code{DESCRIPTION} file of a package
 published on the web interface of the Bioconductor SVN repository.
 
-The command command below imports meta-data for the @code{GenomicRanges}
+The command below imports metadata for the @code{GenomicRanges}
 R package:
 
 @example
@@ -4416,7 +4456,7 @@ guix import cran --archive=bioconductor GenomicRanges
 @end example
 
 @item nix
-Import meta-data from a local copy of the source of the
+Import metadata from a local copy of the source of the
 @uref{http://nixos.org/nixpkgs/, Nixpkgs distribution}@footnote{This
 relies on the @command{nix-instantiate} command of
 @uref{http://nixos.org/nix/, Nix}.}.  Package definitions in Nixpkgs are
@@ -4447,7 +4487,7 @@ guix import nix ~/path/to/nixpkgs libreoffice
 
 @item hackage
 @cindex hackage
-Import meta-data from Haskell community's central package archive
+Import metadata from the Haskell community's central package archive
 @uref{https://hackage.haskell.org/, Hackage}.  Information is taken from
 Cabal files and includes all the relevant information, including package
 dependencies.
@@ -4457,10 +4497,10 @@ Specific command-line options are:
 @table @code
 @item --stdin
 @itemx -s
-Read a Cabal file from the standard input.
+Read a Cabal file from standard input.
 @item --no-test-dependencies
 @itemx -t
-Do not include dependencies required by the test suites only.
+Do not include dependencies required only by the test suites.
 @item --cabal-environment=@var{alist}
 @itemx -e @var{alist}
 @var{alist} is a Scheme alist defining the environment in which the
@@ -4470,10 +4510,10 @@ The value associated with a flag has to be either the symbol
 @code{true} or @code{false}.  The value associated with other keys
 has to conform to the Cabal file format definition.  The default value
 associated with the keys @code{os}, @code{arch} and @code{impl} is
-@samp{linux}, @samp{x86_64} and @samp{ghc} respectively.
+@samp{linux}, @samp{x86_64} and @samp{ghc}, respectively.
 @end table
 
-The command below imports meta-data for the latest version of the
+The command below imports metadata for the latest version of the
 @code{HTTP} Haskell package without including test dependencies and
 specifying the value of the flag @samp{network-uri} as @code{false}:
 
@@ -4490,7 +4530,7 @@ guix import hackage mtl-2.1.3.1
 
 @item elpa
 @cindex elpa
-Import meta-data from an Emacs Lisp Package Archive (ELPA) package
+Import metadata from an Emacs Lisp Package Archive (ELPA) package
 repository (@pxref{Packages,,, emacs, The GNU Emacs Manual}).
 
 Specific command-line options are:
@@ -4535,8 +4575,8 @@ gnu/packages/gettext.scm:29:13: gettext would be upgraded from 0.18.1.1 to 0.18.
 gnu/packages/glib.scm:77:12: glib would be upgraded from 2.34.3 to 2.37.0
 @end example
 
-It does so by browsing each package's FTP directory and determining the
-highest version number of the source tarballs therein.  The command
+It does so by browsing the FTP directory of each package and determining
+the highest version number of the source tarballs therein.  The command
 knows how to update specific types of packages: GNU packages, ELPA
 packages, etc.---see the documentation for @option{--type} below.  The
 are many packages, though, for which it lacks a method to determine
@@ -4544,14 +4584,14 @@ whether a new upstream release is available.  However, the mechanism is
 extensible, so feel free to get in touch with us to add a new method!
 
 When passed @code{--update}, it modifies distribution source files to
-update the version numbers and source tarball hashes of those packages'
+update the version numbers and source tarball hashes of those package
 recipes (@pxref{Defining Packages}).  This is achieved by downloading
 each package's latest source tarball and its associated OpenPGP
 signature, authenticating the downloaded tarball against its signature
 using @command{gpg}, and finally computing its hash.  When the public
 key used to sign the tarball is missing from the user's keyring, an
 attempt is made to automatically retrieve it from a public key server;
-when it's successful, the key is added to the user's keyring; otherwise,
+when this is successful, the key is added to the user's keyring; otherwise,
 @command{guix refresh} reports an error.
 
 The following options are supported:
@@ -4609,6 +4649,8 @@ list of updaters).  Currently, @var{updater} may be one of:
 the updater for GNU packages;
 @item gnome
 the updater for GNOME packages;
+@item xorg
+the updater for X.org packages;
 @item elpa
 the updater for @uref{http://elpa.gnu.org/, ELPA} packages;
 @item cran
@@ -4617,10 +4659,14 @@ the updater for @uref{http://cran.r-project.org/, CRAN} packages;
 the updater for @uref{http://www.bioconductor.org/, Bioconductor} R packages;
 @item pypi
 the updater for @uref{https://pypi.python.org, PyPI} packages.
+@item gem
+the updater for @uref{https://rubygems.org, RubyGems} packages.
+@item github
+the updater for @uref{https://github.com, GitHub} packages.
 @end table
 
-For instance, the following commands only checks for updates of Emacs
-packages hosted at @code{elpa.gnu.org} and updates of CRAN packages:
+For instance, the following command only checks for updates of Emacs
+packages hosted at @code{elpa.gnu.org} and for updates of CRAN packages:
 
 @example
 $ guix refresh --type=elpa,cran
@@ -4703,11 +4749,23 @@ Use @var{host} as the OpenPGP key server when importing a public key.
 
 @end table
 
+The @code{github} updater uses the
+@uref{https://developer.github.com/v3/, GitHub API} to query for new
+releases.  When used repeatedly e.g. when refreshing all packages,
+GitHub will eventually refuse to answer any further API requests.  By
+default 60 API requests per hour are allowed, and a full refresh on all
+GitHub packages in Guix requires more than this.  Authentication with
+GitHub through the use of an API token alleviates these limits.  To use
+an API token, set the environment variable @code{GUIX_GITHUB_TOKEN} to a
+token procured from @uref{https://github.com/settings/tokens} or
+otherwise.
+
+
 @node Invoking guix lint
 @section Invoking @command{guix lint}
-The @command{guix lint} is meant to help package developers avoid common
-errors and use a consistent style.  It runs a number of checks on a
-given set of packages in order to find common mistakes in their
+The @command{guix lint} command is meant to help package developers avoid
+common errors and use a consistent style.  It runs a number of checks on
+a given set of packages in order to find common mistakes in their
 definitions.  Available @dfn{checkers} include (see
 @code{--list-checkers} for a complete list):
 
@@ -4725,8 +4783,8 @@ Identify inputs that should most likely be native inputs.
 @itemx source-file-name
 Probe @code{home-page} and @code{source} URLs and report those that are
 invalid.  Check that the source file name is meaningful, e.g. is not
-just a version number or ``git-checkout'', and should not have a
-@code{file-name} declared (@pxref{origin Reference}).
+just a version number or ``git-checkout'', without a declared
+@code{file-name} (@pxref{origin Reference}).
 
 @item cve
 Report known vulnerabilities found in the Common Vulnerabilities and
@@ -4749,17 +4807,16 @@ If no package is given on the command line, then all packages are checked.
 The @var{options} may be zero or more of the following:
 
 @table @code
+@item --list-checkers
+@itemx -l
+List and describe all the available checkers that will be run on packages
+and exit.
 
 @item --checkers
 @itemx -c
 Only enable the checkers specified in a comma-separated list using the
 names returned by @code{--list-checkers}.
 
-@item --list-checkers
-@itemx -l
-List and describe all the available checkers that will be run on packages
-and exit.
-
 @end table
 
 @node Invoking guix size
@@ -4769,7 +4826,7 @@ The @command{guix size} command helps package developers profile the
 disk usage of packages.  It is easy to overlook the impact of an
 additional dependency added to a package, or the impact of using a
 single output for a package that could easily be split (@pxref{Packages
-with Multiple Outputs}).  These are the typical issues that
+with Multiple Outputs}).  Such are the typical issues that
 @command{guix size} can highlight.
 
 The command can be passed a package specification such as @code{gcc-4.8}
@@ -4796,12 +4853,12 @@ would be returned by:
 $ guix gc -R /gnu/store/@dots{}-coreutils-8.23
 @end example
 
-Here the output shows 3 columns next to store items.  The first column,
+Here the output shows three columns next to store items.  The first column,
 labeled ``total'', shows the size in mebibytes (MiB) of the closure of
 the store item---that is, its own size plus the size of all its
 dependencies.  The next column, labeled ``self'', shows the size of the
-item itself.  The last column shows the ratio of the item's size to the
-space occupied by all the items listed here.
+item itself.  The last column shows the ratio of the size of the item
+itself to the space occupied by all the items listed here.
 
 In this example, we see that the closure of Coreutils weighs in at
 70@tie{}MiB, half of which is taken by libc.  (That libc represents a
@@ -4815,9 +4872,9 @@ dependencies, and measures its size in the store, similar to @command{du
 Coreutils}).
 
 When the given package is @emph{not} in the store, @command{guix size}
-reports information based on information about the available substitutes
-(@pxref{Substitutes}).  This allows it to profile disk usage of store
-items that are not even on disk, only available remotely.
+reports information based on the available substitutes
+(@pxref{Substitutes}).  This makes it possible it to profile disk usage of
+store items that are not even on disk, only available remotely.
 
 The available options are:
 
@@ -4828,7 +4885,7 @@ Use substitute information from @var{urls}.
 @xref{client-substitute-urls, the same option for @code{guix build}}.
 
 @item --map-file=@var{file}
-Write to @var{file} a graphical map of disk usage as a PNG file.
+Write a graphical map of disk usage in PNG format to @var{file}.
 
 For the example above, the map looks like this:
 
@@ -4852,11 +4909,11 @@ Consider packages for @var{system}---e.g., @code{x86_64-linux}.
 @cindex DAG
 Packages and their dependencies form a @dfn{graph}, specifically a
 directed acyclic graph (DAG).  It can quickly become difficult to have a
-mental model of the package DAG, so the @command{guix graph} command is
-here to provide a visual representation of the DAG.  @command{guix
-graph} emits a DAG representation in the input format of
+mental model of the package DAG, so the @command{guix graph} command
+provides a visual representation of the DAG.  @command{guix graph}
+emits a DAG representation in the input format of
 @uref{http://www.graphviz.org/, Graphviz}, so its output can be passed
-directly to Graphviz's @command{dot} command, for instance.  The general
+directly to the @command{dot} command of Graphviz.  The general
 syntax is:
 
 @example
@@ -4877,15 +4934,15 @@ The output looks like this:
 
 Nice little graph, no?
 
-But there's more than one graph!  The one above is concise: it's the
+But there is more than one graph!  The one above is concise: it is the
 graph of package objects, omitting implicit inputs such as GCC, libc,
-grep, etc.  It's often useful to have such a concise graph, but
-sometimes you want to see more details.  @command{guix graph} supports
-several types of graphs, allowing you to choose the level of details:
+grep, etc.  It is often useful to have such a concise graph, but
+sometimes one may want to see more details.  @command{guix graph} supports
+several types of graphs, allowing you to choose the level of detail:
 
 @table @code
 @item package
-This is the default type, the one we used above.  It shows the DAG of
+This is the default type used in the example above.  It shows the DAG of
 package objects, excluding implicit dependencies.  It is concise, but
 filters out many details.
 
@@ -4905,7 +4962,7 @@ guix graph --type=bag-emerged coreutils | dot -Tpdf > dag.pdf
 At the bottom of the graph, we see all the implicit inputs of
 @var{gnu-build-system} (@pxref{Build Systems, @code{gnu-build-system}}).
 
-Now, note that the dependencies of those implicit inputs---that is, the
+Now, note that the dependencies of these implicit inputs---that is, the
 @dfn{bootstrap dependencies} (@pxref{Bootstrapping})---are not shown
 here, for conciseness.
 
@@ -4920,11 +4977,11 @@ Similar to @code{bag}, but also showing origins and their dependencies.
 This is the most detailed representation: It shows the DAG of
 derivations (@pxref{Derivations}) and plain store items.  Compared to
 the above representation, many additional nodes are visible, including
-builds scripts, patches, Guile modules, etc.
+build scripts, patches, Guile modules, etc.
 
 @end table
 
-All the above types correspond to @emph{build-time dependencies}.  The
+All the types above correspond to @emph{build-time dependencies}.  The
 following graph type represents the @emph{run-time dependencies}:
 
 @table @code
@@ -4967,7 +5024,7 @@ guix graph -e '(@@@@ (gnu packages commencement) gnu-make-final)'
 The purpose of @command{guix environment} is to assist hackers in
 creating reproducible development environments without polluting their
 package profile.  The @command{guix environment} tool takes one or more
-packages, builds all of the necessary inputs, and creates a shell
+packages, builds all of their inputs, and creates a shell
 environment to use them.
 
 The general syntax is:
@@ -4983,12 +5040,12 @@ GNU@tie{}Guile:
 guix environment guile
 @end example
 
-If the specified packages are not built yet, @command{guix environment}
-automatically builds them.  The new shell's environment is an augmented
+If the needed dependencies are not built yet, @command{guix environment}
+automatically builds them.  The environment of the new shell is an augmented
 version of the environment that @command{guix environment} was run in.
 It contains the necessary search paths for building the given package
 added to the existing environment variables.  To create a ``pure''
-environment in which the original environment variables have been unset,
+environment, in which the original environment variables have been unset,
 use the @code{--pure} option@footnote{Users sometimes wrongfully augment
 environment variables such as @code{PATH} in their @file{~/.bashrc}
 file.  As a consequence, when @code{guix environment} launches it, Bash
@@ -5001,7 +5058,7 @@ details on Bash start-up files.}.
 
 @vindex GUIX_ENVIRONMENT
 @command{guix environment} defines the @code{GUIX_ENVIRONMENT}
-variable in the shell it spaws.  This allows users to, say, define a
+variable in the shell it spawns.  This allows users to, say, define a
 specific prompt for development environments in their @file{.bashrc}
 (@pxref{Bash Startup Files,,, bash, The GNU Bash Reference Manual}):
 
@@ -5093,6 +5150,13 @@ guix environment --ad-hoc -e '(@@ (gnu) %base-packages)'
 
 starts a shell with all the GuixSD base packages available.
 
+The above commands only the use default output of the given packages.
+To select other outputs, two element tuples can be specified:
+
+@example
+guix environment --ad-hoc -e '(list (@ (gnu packages bash) bash) "include")'
+@end example
+
 @item --load=@var{file}
 @itemx -l @var{file}
 Create an environment for the package or list of packages that the code
@@ -5121,7 +5185,7 @@ runs @command{guile} in an environment where Guile and Guile-SDL are
 available.
 
 Note that this example implicitly asks for the default output of
-@code{guile} and @code{guile-sdl} but it is possible to ask for a
+@code{guile} and @code{guile-sdl}, but it is possible to ask for a
 specific output---e.g., @code{glib:bin} asks for the @code{bin} output
 of @code{glib} (@pxref{Packages with Multiple Outputs}).
 
@@ -5195,7 +5259,7 @@ build} supports (@pxref{Common Build Options}).
 @section Invoking @command{guix publish}
 
 The purpose of @command{guix publish} is to enable users to easily share
-their store with others, which can then use it as a substitute server
+their store with others, who can then use it as a substitute server
 (@pxref{Substitutes}).
 
 When @command{guix publish} runs, it spawns an HTTP server which allows
@@ -5206,7 +5270,7 @@ the @code{hydra.gnu.org} build farm.
 
 For security, each substitute is signed, allowing recipients to check
 their authenticity and integrity (@pxref{Substitutes}).  Because
-@command{guix publish} uses the system's signing key, which is only
+@command{guix publish} uses the signing key of the system, which is only
 readable by the system administrator, it must be started as root; the
 @code{--user} option makes it drop root privileges early on.
 
@@ -5270,12 +5334,12 @@ of the @code{operating-system} declaration (@pxref{guix-publish-service,
 @cindex verifiable builds
 
 Do the binaries provided by this server really correspond to the source
-code it claims to build?  Is this package's build process deterministic?
+code it claims to build?  Is a package build process deterministic?
 These are the questions the @command{guix challenge} command attempts to
 answer.
 
 The former is obviously an important question: Before using a substitute
-server (@pxref{Substitutes}), you'd rather @emph{verify} that it
+server (@pxref{Substitutes}), one had better @emph{verify} that it
 provides the right binaries, and thus @emph{challenge} it.  The latter
 is what enables the former: If package builds are deterministic, then
 independent builds of the package should yield the exact same result,
@@ -5291,7 +5355,7 @@ one store file name should map to exactly one build output.
 mapping by comparing the build outputs of several independent builds of
 any given store item.
 
-The command's output looks like this:
+The command output looks like this:
 
 @smallexample
 $ guix challenge --substitute-urls="http://hydra.gnu.org http://guix.example.org"
@@ -5330,7 +5394,7 @@ results, the inclusion of random numbers, and directory listings sorted
 by inode number.  See @uref{http://reproducible.debian.net/howto/}, for
 more information.
 
-To find out what's wrong with this Git binary, we can do something along
+To find out what is wrong with this Git binary, we can do something along
 these lines (@pxref{Invoking guix archive}):
 
 @example
@@ -5347,11 +5411,11 @@ works great for text files.  When binary files differ, a better option
 is @uref{http://diffoscope.org/, Diffoscope}, a tool that helps
 visualize differences for all kinds of files.
 
-Once you've done that work, you can tell whether the differences are due
+Once you have done that work, you can tell whether the differences are due
 to a non-deterministic build process or to a malicious server.  We try
 hard to remove sources of non-determinism in packages to make it easier
-to verify substitutes, but of course, this is a process, one that
-involves not just Guix but a large part of the free software community.
+to verify substitutes, but of course, this is a process that
+involves not just Guix, but a large part of the free software community.
 In the meantime, @command{guix challenge} is one tool to help address
 the problem.
 
@@ -5364,7 +5428,7 @@ $ guix challenge @var{package}
 @end example
 
 @noindent
-... where @var{package} is a package specification such as
+where @var{package} is a package specification such as
 @code{guile-2.0} or @code{glibc:debug}.
 
 The general syntax is:
@@ -5421,9 +5485,9 @@ guix container exec @var{pid} @var{program} @var{arguments}@dots{}
 @end example
 
 @var{pid} specifies the process ID of the running container.
-@var{program} specifies an executable file name within the container's
-root file system.  @var{arguments} are the additional options that will
-be passed to @var{program}.
+@var{program} specifies an executable file name within the root file
+system of the container.  @var{arguments} are the additional options that
+will be passed to @var{program}.
 
 The following command launches an interactive login shell inside a
 GuixSD container, started by @command{guix system container}, and whose
@@ -5434,7 +5498,7 @@ guix container exec 9001 /run/current-system/profile/bin/bash --login
 @end example
 
 Note that the @var{pid} cannot be the parent process of a container.  It
-must be the container's PID 1 or one of its child processes.
+must be PID 1 of the container or one of its child processes.
 
 @end table
 
@@ -5464,7 +5528,7 @@ running @command{guix package} (@pxref{Invoking guix package}):
 guix package --list-available
 @end example
 
-Our goal has been to provide a practical 100% free software distribution of
+Our goal is to provide a practical 100% free software distribution of
 Linux-based and other variants of GNU, with a focus on the promotion and
 tight integration of GNU components, and an emphasis on programs and
 tools that help users exert that freedom.
@@ -5481,11 +5545,12 @@ Intel 32-bit architecture (IA32), Linux-Libre kernel;
 
 @item armhf-linux
 ARMv7-A architecture with hard float, Thumb-2 and NEON,
-using the EABI hard-float ABI, and Linux-Libre kernel.
+using the EABI hard-float application binary interface (ABI),
+and Linux-Libre kernel.
 
 @item mips64el-linux
 little-endian 64-bit MIPS processors, specifically the Loongson series,
-n32 application binary interface (ABI), and Linux-Libre kernel.
+n32 ABI, and Linux-Libre kernel.
 
 @end table
 
@@ -5493,7 +5558,7 @@ GuixSD itself is currently only available on @code{i686} and @code{x86_64}.
 
 @noindent
 For information on porting to other architectures or kernels,
-@xref{Porting}.
+@pxref{Porting}.
 
 @menu
 * System Installation::         Installing the whole operating system.
@@ -5527,6 +5592,15 @@ link that follows: @pxref{Help,,, info, Info: An Introduction}.  Hit
 @kbd{l} afterwards to come back here.
 @end ifinfo
 
+@menu
+* Limitations::                         What you can expect.
+* USB Stick Installation::              Preparing the installation medium.
+* Preparing for Installation::          Networking, partitioning, etc.
+* Proceeding with the Installation::    The real thing.
+* Building the Installation Image::     How this comes to be.
+@end menu
+
+@node Limitations
 @subsection Limitations
 
 As of version @value{VERSION}, the Guix System Distribution (GuixSD) is
@@ -5534,7 +5608,7 @@ not production-ready.  It may contain bugs and lack important
 features.  Thus, if you are looking for a stable production system that
 respects your freedom as a computer user, a good solution at this point
 is to consider @url{http://www.gnu.org/distros/free-distros.html, one of
-more established GNU/Linux distributions}.  We hope you can soon switch
+the more established GNU/Linux distributions}.  We hope you can soon switch
 to the GuixSD without fear, of course.  In the meantime, you can
 also keep using your distribution and try out the package manager on top
 of it (@pxref{Installation}).
@@ -5550,7 +5624,7 @@ get a feel of what that means.)
 
 @item
 The system does not yet provide full GNOME and KDE desktops.  Xfce and
-Enlightenment are available though, if graphical desktop environments
+Enlightenment are available, though, if graphical desktop environments
 are your thing, as well as a number of X11 window managers.
 
 @item
@@ -5561,14 +5635,15 @@ Few system services are currently supported out-of-the-box
 (@pxref{Services}).
 
 @item
-More than 2,000 packages are available, but you may
+More than 3,000 packages are available, but you may
 occasionally find that a useful package is missing.
 @end itemize
 
-You've been warned.  But more than a disclaimer, this is an invitation
-to report issues (and success stories!), and join us in improving it.
+You have been warned!  But more than a disclaimer, this is an invitation
+to report issues (and success stories!), and to join us in improving it.
 @xref{Contributing}, for more info.
 
+@node USB Stick Installation
 @subsection USB Stick Installation
 
 An installation image for USB sticks can be downloaded from
@@ -5598,8 +5673,8 @@ xz -d guixsd-usb-install-@value{VERSION}.@var{system}.xz
 @end example
 
 @item
-Insert a USB stick of 1@tie{}GiB or more in your machine, and determine
-its device name.  Assuming that USB stick is known as @file{/dev/sdX},
+Insert a USB stick of 1@tie{}GiB or more into your machine, and determine
+its device name.  Assuming that the USB stick is known as @file{/dev/sdX},
 copy the image with:
 
 @example
@@ -5613,6 +5688,7 @@ Once this is done, you should be able to reboot the system and boot from
 the USB stick.  The latter usually requires you to get in the BIOS' boot
 menu, where you can choose to boot from the USB stick.
 
+@node Preparing for Installation
 @subsection Preparing for Installation
 
 Once you have successfully booted the image on the USB stick, you should
@@ -5623,47 +5699,123 @@ Introduction}).  The installation system runs the GPM mouse daemon,
 which allows you to select text with the left mouse button and to paste
 it with the middle button.
 
-To install the system, you would:
+@subsubsection Keyboard Layout
 
-@enumerate
+@cindex keyboard layout
+The installation image uses the US qwerty keyboard layout.  If you want
+to change it, you can use the @command{loadkeys} command.  For example,
+the following command selects the Dvorak keyboard layout:
 
-@item
-Configure the network, by running:
+@example
+loadkeys dvorak
+@end example
+
+See the files under @file{/run/current-system/profile/share/keymaps} for
+a list of available keyboard layouts.  Run @command{man loadkeys} for
+more information.
+
+@subsubsection Networking
+
+Run the following command see what your network interfaces are called:
 
 @example
-ifconfig eno1 up && dhclient eno1
+ifconfig -a
 @end example
 
-to get an automatically assigned IP address from the wired
-network interface controller@footnote{
 @c http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-net_id.c#n20
-The name @code{eno1} is for the first on-board Ethernet controller.  The
-interface name for an Ethernet controller that is in the first slot of
-the first PCI bus, for instance, would be @code{enp1s0}.  Use
-@command{ifconfig -a} to list all the available network interfaces.},
-or using the @command{ifconfig} command.
+Wired interfaces have a name starting with @samp{e}; for example, the
+interface corresponding to the first on-board Ethernet controller is
+called @samp{eno1}.  Wireless interfaces have a name starting with
+@samp{w}, like @samp{w1p2s0}.
 
-The system automatically loads drivers for your network interface
-controllers.
+@table @asis
+@item Wired connection
+To configure a wired network run the following command, substituting
+@var{interface} with the name of the wired interface you want to use.
+
+@example
+ifconfig @var{interface} up
+@end example
+
+@item Wireless connection
+To configure wireless networking, you can create a configuration file
+for the @command{wpa_supplicant} configuration tool (its location is not
+important) using one of the available text editors such as
+@command{zile}:
+
+@example
+zile wpa_supplicant.conf
+@end example
+
+As an example, the following stanza can go to this file and will work
+for many wireless networks, provided you give the actual SSID and
+passphrase for the network you are connecting to:
+
+@example
+network=@{
+  ssid=@var{my-ssid}
+  key_mgmt=WPA-PSK
+  psk="the network's secret passphrase"
+@}
+@end example
+
+Start the wireless service and run it in the background with the
+following command (substitute @var{interface} with the name of the
+network interface you want to use):
+
+@example
+wpa_supplicant -c wpa_supplicant.conf -i @var{interface} -B
+@end example
+
+Run @command{man wpa_supplication} for more information.
+@end table
+
+At this point, you need to acquire an IP address.  On a network where IP
+addresses are automatically assigned @i{via} DHCP, you can run:
+
+@example
+dhclient @var{interface}
+@end example
+
+Try to ping a server to see if networking is up and running:
+
+@example
+ping -c 3 gnu.org
+@end example
 
 Setting up network access is almost always a requirement because the
 image does not contain all the software and tools that may be needed.
 
-@item
-Unless this has already been done, you must partition, and then format
-the target partition.
+@subsubsection Disk Partitioning
+
+Unless this has already been done, the next step is to partition, and
+then format the target partition(s).
+
+The installation image includes several partitioning tools, including
+Parted (@pxref{Overview,,, parted, GNU Parted User Manual}),
+@command{fdisk}, and @command{cfdisk}.  Run it and set up your disk with
+the partition layout you want:
+
+@example
+cfdisk
+@end example
+
+Once you are done partitioning the target hard disk drive, you have to
+create a file system on the relevant partition(s)@footnote{Currently
+GuixSD pretty much assumes an ext4 file system.  In particular, code
+that reads partition UUIDs and labels only works with ext4.  This will
+be fixed in the future.}.
 
 Preferably, assign partitions a label so that you can easily and
 reliably refer to them in @code{file-system} declarations (@pxref{File
 Systems}).  This is typically done using the @code{-L} option of
-@command{mkfs.ext4} and related commands.
+@command{mkfs.ext4} and related commands.  So, assuming the target root
+partition lives at @file{/dev/sda1}, a file system with the label
+@code{my-root} can be created with:
 
-Be sure that your partition labels match the value of their respective
-@code{device} fields in your @code{file-system} configuration, if your
-@code{file-system} configuration sets the value of @code{title} to
-@code{'label}, as do the example configurations found on the USB
-installation image under @file{/etc/configuration} (@pxref{Using the
-Configuration System}).
+@example
+mkfs.ext4 -L my-root /dev/sda1
+@end example
 
 @c FIXME: Uncomment this once GRUB fully supports encrypted roots.
 @c A typical command sequence may be:
@@ -5676,37 +5828,66 @@ Configuration System}).
 @c # mkfs.ext4 -L my-root /dev/mapper/my-partition
 @c @end example
 
-The installation image includes Parted (@pxref{Overview,,, parted, GNU
-Parted User Manual}), @command{fdisk}, Cryptsetup/LUKS for disk
-encryption, and e2fsprogs, the suite of tools to manipulate
-ext2/ext3/ext4 file systems.
+In addition to e2fsprogs, the suite of tools to manipulate
+ext2/ext3/ext4 file systems, the installation image includes
+Cryptsetup/LUKS for disk encryption.
 
-@item
-Once that is done, mount the target root partition under @file{/mnt}.
+Once that is done, mount the target root partition under @file{/mnt}
+with a command like (again, assuming @file{/dev/sda1} is the root
+partition):
 
-@item
-Lastly, run @code{herd start cow-store /mnt}.
+@example
+mount /dev/sda1 /mnt
+@end example
 
-This will make @file{/gnu/store} copy-on-write, such that packages added
-to it during the installation phase will be written to the target disk
-rather than kept in memory.
+@node Proceeding with the Installation
+@subsection Proceeding with the Installation
 
-@end enumerate
+With the target partitions ready and the target root mounted on
+@file{/mnt}, we're ready to go.  First, run:
 
+@example
+herd start cow-store /mnt
+@end example
 
-@subsection Proceeding with the Installation
+This makes @file{/gnu/store} copy-on-write, such that packages added to
+it during the installation phase are written to the target disk rather
+than kept in memory.
 
-With the target partitions ready, you now have to edit a file and
+Next, you have to edit a file and
 provide the declaration of the operating system to be installed.  To
 that end, the installation system comes with two text editors: GNU nano
 (@pxref{Top,,, nano, GNU nano Manual}), and GNU Zile, an Emacs clone.
 It is better to store that file on the target root file system, say, as
 @file{/mnt/etc/config.scm}.
 
-@xref{Using the Configuration System}, for examples of operating system
-configurations.  These examples are available under
-@file{/etc/configuration} in the installation image, so you can copy
-them and use them as a starting point for your own configuration.
+@xref{Using the Configuration System}, for an overview of the
+configuration file.  The example configurations discussed in that
+section are available under @file{/etc/configuration} in the
+installation image.  Thus, to get started with a system configuration
+providing a graphical display server (a ``desktop'' system), you can run
+something along these lines:
+
+@example
+# mkdir /mnt/etc
+# cp /etc/configuration/desktop.scm /mnt/etc/config.scm
+# zile /mnt/etc/config.scm
+@end example
+
+You should pay attention to what your configuration file contains, and
+in particular:
+
+@itemize
+@item
+Make sure the @code{grub-configuration} form refers to the device you
+want to install GRUB on.
+
+@item
+Be sure that your partition labels match the value of their respective
+@code{device} fields in your @code{file-system} configuration, assuming
+your @code{file-system} configuration sets the value of @code{title} to
+@code{'label}.
+@end itemize
 
 Once you are done preparing the configuration file, the new system must
 be initialized (remember that the target root file system is mounted
@@ -5717,7 +5898,7 @@ guix system init /mnt/etc/config.scm /mnt
 @end example
 
 @noindent
-This will copy all the necessary files, and install GRUB on
+This copies all the necessary files and installs GRUB on
 @file{/dev/sdX}, unless you pass the @option{--no-grub} option.  For
 more information, @pxref{Invoking guix system}.  This command may trigger
 downloads or builds of missing packages, which can take some time.
@@ -5733,6 +5914,7 @@ Join us on @code{#guix} on the Freenode IRC network or on
 @file{guix-devel@@gnu.org} to share your experience---good or not so
 good.
 
+@node Building the Installation Image
 @subsection Building the Installation Image
 
 The installation image described above was built using the @command{guix
@@ -6137,7 +6319,12 @@ is interpreted as a partition label name; when it is @code{uuid},
 @code{device} is interpreted as a partition unique identifier (UUID).
 
 UUIDs may be converted from their string representation (as shown by the
-@command{tune2fs -l} command) using the @code{uuid} form, like this:
+@command{tune2fs -l} command) using the @code{uuid} form@footnote{The
+@code{uuid} form expects 16-byte UUIDs as defined in
+@uref{https://tools.ietf.org/html/rfc4122, RFC@tie{}4122}.  This is the
+form of UUID used by the ext2 family of file systems and others, but it
+is different from ``UUIDs'' found in FAT file systems, for instance.},
+like this:
 
 @example
 (file-system
@@ -6452,17 +6639,17 @@ Usually, you will want to specify the default locale for the machine
 using the @code{locale} field of the @code{operating-system} declaration
 (@pxref{operating-system Reference, @code{locale}}).
 
-That locale must be among the @dfn{locale definitions} that are known to
-the system---and these are specified in the @code{locale-definitions}
-slot of @code{operating-system}.  The default value includes locale
-definitions for some widely used locales, but not for all the available
-locales, in order to save space.
+The selected locale is automatically added to the @dfn{locale
+definitions} known to the system if needed, with its codeset inferred
+from its name---e.g., @code{bo_CN.utf8} will be assumed to use the
+@code{UTF-8} codeset.  Additional locale definitions can be specified in
+the @code{locale-definitions} slot of @code{operating-system}---this is
+useful, for instance, if the codeset could not be inferred from the
+locale name.  The default set of locale definitions includes some widely
+used locales, but not all the available locales, in order to save space.
 
-If the locale specified in the @code{locale} field is not among the
-definitions listed in @code{locale-definitions}, @command{guix system}
-raises an error.  In that case, you should add the locale definition to
-the @code{locale-definitions} field.  For instance, to add the North
-Frisian locale for Germany, the value of that field may be:
+For instance, to add the North Frisian locale for Germany, the value of
+that field may be:
 
 @example
 (cons (locale-definition
@@ -6844,6 +7031,7 @@ Run @var{udev}, which populates the @file{/dev} directory dynamically.
 @end deffn
 
 @deffn {Scheme Procedure} console-keymap-service @var{file}
+@cindex keyboard layout
 Return a service to load console keymap from @var{file} using
 @command{loadkeys} command.
 @end deffn
@@ -9204,7 +9392,7 @@ guix system @var{options}@dots{} @var{action} @var{file}
 
 @var{file} must be the name of a file containing an
 @code{operating-system} declaration.  @var{action} specifies how the
-operating system is instantiate.  Currently the following values are
+operating system is instantiated.  Currently the following values are
 supported:
 
 @table @code
@@ -9439,7 +9627,7 @@ example graph.
 @end table
 
 @node Running GuixSD in a VM
-@subsection Running GuixSD in a virtual machine
+@subsection Running GuixSD in a Virtual Machine
 
 One way to run GuixSD in a virtual machine (VM) is to build a GuixSD
 virtual machine image using @command{guix system vm-image}
@@ -9670,7 +9858,7 @@ the composition of the extensions.
 
 Udev extensions are composed into a list of rules, but the udev service
 value is itself a @code{<udev-configuration>} record.  So here, we
-extend that record by appending the list of rules is contains to the
+extend that record by appending the list of rules it contains to the
 list of contributed rules.
 @end table
 
@@ -9864,11 +10052,11 @@ extend it by passing it lists of packages to add to the system profile.
 
 @cindex PID 1
 @cindex init system
-The @code{(gnu services shepherd)} provides a way to define services
-managed by the GNU@tie{}Shepherd, which is GuixSD initialization
-system---the first process that is started when the system boots,
-aka. PID@tie{}1 (@pxref{Introduction,,, shepherd, The GNU Shepherd
-Manual}).
+The @code{(gnu services shepherd)} module provides a way to define
+services managed by the GNU@tie{}Shepherd, which is the GuixSD
+initialization system---the first process that is started when the
+system boots, aka. PID@tie{}1 (@pxref{Introduction,,, shepherd, The GNU
+Shepherd Manual}).
 
 Services in the Shepherd can depend on each other.  For instance, the
 SSH daemon may need to be started after the syslog daemon has been
@@ -10138,7 +10326,7 @@ Free software packages are usually distributed in the form of
 all the source files.  Adding a package to the distribution means
 essentially two things: adding a @dfn{recipe} that describes how to
 build the package, including a list of other packages required to build
-it, and adding @dfn{package meta-data} along with that recipe, such as a
+it, and adding @dfn{package metadata} along with that recipe, such as a
 description and licensing information.
 
 In Guix all this information is embodied in @dfn{package definitions}.
@@ -10322,7 +10510,26 @@ field to, say, 7 digits.  It avoids an aesthetic annoyance (assuming
 aesthetics have a role to play here) as well as problems related to OS
 limits such as the maximum shebang length (127 bytes for the Linux
 kernel.)  It is best to use the full commit identifiers in
-@code{origin}s, though, to avoid ambiguities.
+@code{origin}s, though, to avoid ambiguities.  A typical package
+definition may look like this:
+
+@example
+(define my-package
+  (let ((commit "c3f29bc928d5900971f65965feaae59e1272a3f7"))
+    (package
+      (version (string-append "0.9-1."
+                              (string-take commit 7)))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url "git://example.org/my-package.git")
+                      (commit commit)))
+                (sha256 (base32 "1mbikn@dots{}"))
+                (file-name (string-append "my-package-" version
+                                          "-checkout"))))
+      ;; @dots{}
+      )))
+@end example
 
 @node Synopses and Descriptions
 @subsection Synopses and Descriptions
diff --git a/doc/htmlxref.cnf b/doc/htmlxref.cnf
new file mode 100644
index 0000000000..fee1b4c9d8
--- /dev/null
+++ b/doc/htmlxref.cnf
@@ -0,0 +1,652 @@
+# htmlxref.cnf - reference file for free Texinfo manuals on the web.
+# Modified by Ludovic Courtès <ludo@gnu.org> for the GNU Guix manual.
+
+htmlxrefversion=2016-02-21.21; # UTC
+
+# Copyright 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
+# 
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+#
+# The latest version of this file is available at
+# http://ftpmirror.gnu.org/texinfo/htmlxref.cnf.
+# Email corrections or additions to bug-texinfo@gnu.org.
+# The primary goal is to list all relevant GNU manuals;
+# other free manuals are also welcome.
+#
+# To be included in this list, a manual must:
+#
+# - have a generic url, e.g., no version numbers;
+# - have a unique file name (e.g., manual identifier), i.e., be related to the
+#   package name.  Things like "refman" or "tutorial" don't work.
+# - follow the naming convention for nodes described at
+# http://www.gnu.org/software/texinfo/manual/texinfo/html_node/HTML-Xref.html
+#   This is what makeinfo and texi2html implement.
+# 
+# Unless the above criteria are met, it's not possible to generate
+# reliable cross-manual references.
+# 
+# For information on automatically generating all the useful formats for
+# a manual to put on the web, see
+# http://www.gnu.org/prep/maintain/html_node/Manuals-on-Web-Pages.html.
+
+# For people editing this file: when a manual named foo is related to a
+# package named bar, the url should contain a variable reference ${BAR}.
+# Otherwise, the gnumaint scripts have no way of knowing they are
+# associated, and thus gnu.org/manual can't include them.
+
+# shorten references to manuals on www.gnu.org.
+G = http://www.gnu.org
+GS = ${G}/software
+
+3dldf		mono	${GS}/3dldf/manual/user_ref/3DLDF.html
+3dldf		node	${GS}/3dldf/manual/user_ref/
+
+alive		mono	${GS}/alive/manual/alive.html
+alive		node	${GS}/alive/manual/html_node/
+
+anubis		chapter	${GS}/anubis/manual/html_chapter/
+anubis		section	${GS}/anubis/manual/html_section/
+anubis		node	${GS}/anubis/manual/html_node/
+
+artanis		mono	${GS}/artanis/manual/artanis.html
+artanis		node	${GS}/artanis/manual/html_node/
+
+aspell		section	http://aspell.net/man-html/index.html
+
+auctex		mono	${GS}/auctex/manual/auctex.html
+auctex		node	${GS}/auctex/manual/auctex/
+
+autoconf	mono	${GS}/autoconf/manual/autoconf.html
+autoconf	node	${GS}/autoconf/manual/html_node/
+
+autogen		mono	${GS}/autogen/manual/html_mono/autogen.html
+autogen		chapter	${GS}/autogen/manual/html_chapter/
+autogen		node	${GS}/autoconf/manual/html_node/
+
+automake	mono	${GS}/automake/manual/automake.html
+automake	node	${GS}/automake/manual/html_node/
+
+avl		node	http://www.stanford.edu/~blp/avl/libavl.html/
+
+bash		mono	${GS}/bash/manual/bash.html
+bash		node	${GS}/bash/manual/html_node/
+
+BINUTILS = http://sourceware.org/binutils/docs
+binutils	node	${BINUTILS}/binutils/
+ as		node	${BINUTILS}/as/
+ bfd		node	${BINUTILS}/bfd/
+ gprof		node	${BINUTILS}/gprof/
+ ld		node	${BINUTILS}/ld/
+
+bison		mono	${GS}/bison/manual/bison.html
+bison		node	${GS}/bison/manual/html_node/
+
+bpel2owfn	mono	${GS}/bpel2owfn/manual/2.0.x/bpel2owfn.html
+
+ccd2cue		mono	${GS}/ccd2cue/manual/ccd2cue.html
+ccd2cue		node	${GS}/ccd2cue/manual/html_node/
+
+cflow		mono	${GS}/cflow/manual/cflow.html
+cflow		node	${GS}/cflow/manual/html_node/
+
+chess		mono	${GS}/chess/manual/gnuchess.html
+chess		node	${GS}/chess/manual/html_node/
+
+combine		mono	${GS}/combine/manual/combine.html
+combine		chapter	${GS}/combine/manual/html_chapter/
+combine		section	${GS}/combine/manual/html_section/
+combine		node	${GS}/combine/manual/html_node/
+
+complexity	mono	${GS}/complexity/manual/complexity.html
+complexity	node	${GS}/complexity/manual/html_node/
+
+coreutils	mono	${GS}/coreutils/manual/coreutils
+coreutils	node	${GS}/coreutils/manual/html_node/
+
+cpio		mono	${GS}/cpio/manual/cpio
+cpio		node	${GS}/cpio/manual/html_node/
+
+cssc		node	${GS}/cssc/manual/
+
+#cvs cannot be handled here; see http://ximbiot.com/cvs/manual.
+
+ddd		mono	${GS}/ddd/manual/html_mono/ddd.html
+
+ddrescue	mono	${GS}/ddrescue/manual/ddrescue_manual.html
+
+DICO = http://puszcza.gnu.org.ua/software/dico/manual
+dico		mono	${DICO}/dico.html
+dico		chapter	${DICO}/html_chapter/
+dico		section	${DICO}/html_section/
+dico		node	${DICO}/html_node/
+
+diffutils	mono	${GS}/diffutils/manual/diffutils
+diffutils	node	${GS}/diffutils/manual/html_node/
+
+ed		mono	${GS}/ed/manual/ed_manual.html
+
+EMACS = ${GS}/emacs/manual
+emacs		mono	${EMACS}/html_mono/emacs.html
+emacs		node	${EMACS}/html_node/emacs/
+ #
+ ada-mode	mono	${EMACS}/html_mono/ada-mode.html
+ ada-mode	node	${EMACS}/html_node/ada-mode/
+ #
+ autotype	mono	${EMACS}/html_mono/autotype.html
+ autotype	node	${EMACS}/html_node/autotype/
+ #
+ ccmode		mono	${EMACS}/html_mono/ccmode.html
+ ccmode		node	${EMACS}/html_node/ccmode/
+ #
+ cl		mono	${EMACS}/html_mono/cl.html
+ cl		node	${EMACS}/html_node/cl/
+ #
+ ebrowse	mono	${EMACS}/html_mono/ebrowse.html
+ ebrowse	node	${EMACS}/html_node/ebrowse/
+ #
+ ediff		mono	${EMACS}/html_mono/ediff.html
+ ediff		node	${EMACS}/html_node/ediff/
+ #
+ eieio		mono	${EMACS}/html_mono/eieio.html
+ eieio		node	${EMACS}/html_node/eieio/
+ #
+ elisp		mono	${EMACS}/html_mono/elisp.html
+ elisp		node	${EMACS}/html_node/elisp/
+ #
+ epa		mono	${EMACS}/html_mono/epa.html
+ epa		node	${EMACS}/html_node/epa/
+ #
+ erc		mono	${EMACS}/html_mono/erc.html
+ erc		node	${EMACS}/html_node/erc/
+ #
+ dired-x	mono	${EMACS}/html_mono/dired-x.html
+ dired-x	node	${EMACS}/html_node/dired-x/
+ #
+ eshell		mono	${EMACS}/html_mono/eshell.html
+ eshell		node	${EMACS}/html_node/eshell/
+ #
+ flymake	mono	${EMACS}/html_mono/flymake.html
+ flymake	node	${EMACS}/html_node/flymake/
+ #
+ gnus		mono	${EMACS}/html_mono/gnus.html
+ gnus		node	${EMACS}/html_node/gnus/
+ #
+ idlwave	mono	${EMACS}/html_mono/idlwave.html
+ idlwave	node	${EMACS}/html_node/idlwave/
+ #
+ message	mono	${EMACS}/html_mono/message.html
+ message	node	${EMACS}/html_node/message/
+ #
+ mh-e		mono	${EMACS}/html_mono/mh-e.html
+ mh-e		node	${EMACS}/html_node/mh-e/
+ #
+ nxml-mode	mono	${EMACS}/html_mono/nxml-mode.html
+ nxml-mode	node	${EMACS}/html_node/nxml-mode/
+ #
+ org		mono	${EMACS}/html_mono/org.html
+ org		node	${EMACS}/html_node/org/
+ #
+ pcl-cvs	mono	${EMACS}/html_mono/pcl-cvs.html
+ pcl-cvs	node	${EMACS}/html_node/pcl-cvs/
+ #
+ rcirc		mono	${EMACS}/html_mono/rcirc.html
+ rcirc		node	${EMACS}/html_node/rcirc/
+ #
+ semantic	mono	${EMACS}/html_mono/semantic.html
+ semantic	node	${EMACS}/html_node/semantic/
+ #
+ smtp		mono	${EMACS}/html_mono/smtpmail.html
+ smtp		node	${EMACS}/html_node/smtpmail/
+ #
+ speedbar	mono	${EMACS}/html_mono/speedbar.html
+ speedbar	node	${EMACS}/html_node/speedbar/
+ #
+ tramp		mono	${EMACS}/html_mono/tramp.html
+ tramp		node	${EMACS}/html_node/tramp/
+ #
+ vip		mono	${EMACS}/html_mono/vip.html
+ vip		node	${EMACS}/html_node/vip/
+ #
+ viper		mono	${EMACS}/html_mono/viper.html
+ viper		node	${EMACS}/html_node/viper/
+ #
+ woman		mono	${EMACS}/html_mono/woman.html
+ woman		node	${EMACS}/html_node/woman/
+ # (end emacs manuals)
+
+easejs		mono	${GS}/easejs/manual/easejs.html
+easejs		node	${GS}/easejs/manual/
+
+emacs-muse	node	${GS}/emacs-muse/manual/muse.html
+emacs-muse	node	${GS}/emacs-muse/manual/html_node/
+
+emms		node	${GS}/emms/manual/
+
+findutils	mono	${GS}/findutils/manual/html_mono/find.html
+findutils	node	${GS}/findutils/manual/html_node/find_html
+
+FLEX = http://flex.sourceforge.net
+flex		node	${FLEX}/manual/
+
+gama		mono	${GS}/gama/manual/gama.html
+gama		node	${GS}/gama/manual/html_node/
+
+GAWK = ${GS}/gawk/manual
+gawk		mono	${GAWK}/gawk.html
+gawk		node	${GAWK}/html_node/
+ gawkinet	mono	${GAWK}/gawkinet/gawkinet.html
+ gawkinet	node	${GAWK}/gawkinet/html_node/
+
+gcal		mono	${GS}/gcal/manual/gcal.html
+gcal		node	${GS}/gcal/manual/html_node/
+
+GCC = http://gcc.gnu.org/onlinedocs
+gcc		node	${GCC}/gcc/
+ cpp		node	${GCC}/cpp/
+ gcj		node	${GCC}/gcj/
+ gfortran	node	${GCC}/gfortran/
+ gnat_rm	node	${GCC}/gnat_rm/
+ gnat_ugn_unw	node	${GCC}/gnat_ugn_unw/
+ libgomp	node	${GCC}/libgomp/
+ libstdc++	node	${GCC}/libstdc++/
+ #
+ gccint		node	${GCC}/gccint/
+ cppinternals	node	${GCC}/cppinternals/
+ gfc-internals	node	${GCC}/gfc-internals/
+ gnat-style	node	${GCC}/gnat-style/
+ libiberty	node	${GCC}/libiberty/
+
+GDB = http://sourceware.org/gdb/current/onlinedocs
+gdb		node	${GDB}/gdb/
+ stabs		node	${GDB}/stabs/
+
+GDBM = http://www.gnu.org.ua/software/gdbm/manual
+gdbm		mono	${GDBM}/gdbm.html
+gdbm		chapter	${GDBM}/html_chapter/
+gdbm		section ${GDBM}/html_section/
+gdbm		node	${GDBM}/html_node/
+
+gettext		mono	${GS}/gettext/manual/gettext.html
+gettext		node	${GS}/gettext/manual/html_node/
+
+gforth		node	http://www.complang.tuwien.ac.at/forth/gforth/Docs-html/
+
+global		mono	${GS}/global/manual/global.html
+
+gmediaserver	node	${GS}/gmediaserver/manual/
+
+gmp		node	http://www.gmplib.org/manual/
+
+gnu-arch	node	${GS}/gnu-arch/tutorial/
+
+gnu-c-manual	mono	${GS}/gnu-c-manual/gnu-c-manual.html
+
+gnu-crypto	node	${GS}/gnu-crypto/manual/
+
+gnubg		mono	${GS}/gnubg/manual/gnubg.html
+gnubg		node	${GS}/gnubg/manual/html_node/
+
+gnubik		mono	${GS}/gnubik/manual/gnubik.html
+gnubik		node	${GS}/gnubik/manual/html_node/
+
+gnulib		mono	${GS}/gnulib/manual/gnulib.html
+gnulib		node	${GS}/gnulib/manual/html_node/
+
+GNUN = ${GS}/trans-coord/manual
+gnun		mono	${GNUN}/gnun/gnun.html
+gnun		node	${GNUN}/gnun/html_node/
+ web-trans	mono	${GNUN}/web-trans/web-trans.html
+ web-trans	node	${GNUN}/web-trans/html_node/
+
+GNUPG = http://www.gnupg.org/documentation/manuals
+gnupg		node	${GNUPG}/gnupg/
+ dirmngr	node	${GNUPG}/dirmngr/
+ gcrypt		node	${GNUPG}/gcrypt/
+ libgcrypt	node	${GNUPG}/gcrypt/
+ ksba		node	${GNUPG}/ksba/
+ assuan		node	${GNUPG}/assuan/
+ gpgme		node	${GNUPG}/gpgme/
+
+gnuprologjava	node	${GS}/gnuprologjava/manual/
+
+gnuschool	mono	${GS}/gnuschool/gnuschool.html
+
+GNUSTANDARDS = ${G}/prep
+ maintain	mono	${GNUSTANDARDS}/maintain/maintain.html
+ maintain	node	${GNUSTANDARDS}/maintain/html_node/
+ #
+ standards	mono	${GNUSTANDARDS}/standards/standards.html
+ standards	node	${GNUSTANDARDS}/standards/html_node/
+
+gnutls		mono	http://gnutls.org/manual/gnutls.html
+gnutls		node	http://gnutls.org/manual/html_node/
+
+gnutls-guile	mono	http://gnutls.org/manual/gnutls-guile.html
+gnutls-guile	node	http://gnutls.org/manual/gnutls-guile/index.html
+
+gperf		mono	${GS}/gperf/manual/gperf.html
+gperf		node	${GS}/gperf/manual/html_node/
+
+grep		mono	${GS}/grep/manual/grep.html
+grep		node	${GS}/grep/manual/html_node/
+
+groff		node	${GS}/groff/manual/html_node/
+
+GRUB = ${GS}/grub/manual
+  grub		mono	${GRUB}/grub.html
+  grub		node	${GRUB}/html_node/
+  #
+  multiboot	mono	${GRUB}/multiboot/multiboot.html
+  multiboot	node	${GRUB}/multiboot/html_node/
+
+gsasl		mono	${GS}/gsasl/manual/gsasl.html
+gsasl		node	${GS}/gsasl/manual/html_node/
+
+gsl		node	${GS}/gsl/manual/html_node/
+
+gsrc		mono	${GS}/gsrc/manual/gsrc.html
+gsrc		node	${GS}/gsrc/manual/html_node/
+
+gss		mono	${GS}/gss/manual/gss.html
+gss		node	${GS}/gss/manual/html_node/
+
+gtypist		mono	${GS}/gtypist/doc/
+
+guile		mono	${GS}/guile/manual/guile.html
+guile		node	${GS}/guile/manual/html_node/
+
+guile-avahi	mono	http://nongnu.org/guile-avahi/doc/guile-avahi.html
+
+GUILE_GNOME = ${GS}/guile-gnome/docs
+ gobject 	node	${GUILE_GNOME}/gobject/html/
+ glib		node	${GUILE_GNOME}/glib/html/
+ atk		node	${GUILE_GNOME}/atk/html/
+ pango		node	${GUILE_GNOME}/pango/html/
+ pangocairo	node	${GUILE_GNOME}/pangocairo/html/
+ gdk		node	${GUILE_GNOME}/gdk/html/
+ gtk		node	${GUILE_GNOME}/gtk/html/
+ libglade	node	${GUILE_GNOME}/libglade/html/
+ gnome-vfs	node	${GUILE_GNOME}/gnome-vfs/html/
+ libgnomecanvas	node	${GUILE_GNOME}/libgnomecanvas/html/
+ gconf		node	${GUILE_GNOME}/gconf/html/
+ libgnome	node	${GUILE_GNOME}/libgnome/html/
+ libgnomeui	node	${GUILE_GNOME}/libgnomeui/html/
+ corba		node	${GUILE_GNOME}/corba/html/
+ clutter	node	${GUILE_GNOME}/clutter/html/
+ clutter-glx	node	${GUILE_GNOME}/clutter-glx/html/
+
+guile-gtk	node	${GS}/guile-gtk/docs/guile-gtk/
+
+guile-rpc	mono	${GS}/guile-rpc/manual/guile-rpc.html
+guile-rpc	node	${GS}/guile-rpc/manual/html_node/
+
+guix		mono	${GS}/guix/manual/guix.html
+guix		node	${GS}/guix/manual/html_node/
+
+gv		mono	${GS}/gv/manual/gv.html
+gv		node	${GS}/gv/manual/html_node/
+
+gzip		mono	${GS}/gzip/manual/gzip.html
+gzip		node	${GS}/gzip/manual/html_node/
+
+hello		mono	${GS}/hello/manual/hello.html
+hello		node	${GS}/hello/manual/html_node/
+
+help2man	mono	${GS}/help2man/help2man.html
+
+idutils		mono	${GS}/idutils/manual/idutils.html
+idutils		node	${GS}/idutils/manual/html_node/
+
+inetutils	mono	${GS}/inetutils/manual/inetutils.html
+inetutils	node	${GS}/inetutils/manual/html_node/
+
+jwhois		mono	${GS}/jwhois/manual/jwhois.html
+jwhois		node	${GS}/jwhois/manual/html_node/
+
+libc		mono	${GS}/libc/manual/html_mono/libc.html
+libc		node	${GS}/libc/manual/html_node/
+
+LIBCDIO = ${GS}/libcdio
+ libcdio	mono	${LIBCDIO}/libcdio.html
+ cd-text	mono	${LIBCDIO}/cd-text-format.html
+
+libextractor	mono	${GS}/libextractor/manual/libextractor.html
+libextractor	node	${GS}/libextractor/manual/html_node/
+
+libidn		mono	${GS}/libidn/manual/libidn.html
+libidn		node	${GS}/libidn/manual/html_node/
+
+librejs		mono	${GS}/librejs/manual/librejs.html
+librejs		node	${GS}/librejs/manual/html_node/
+
+libmatheval	mono	${GS}/libmatheval/manual/libmatheval.html
+
+LIBMICROHTTPD = ${GS}/libmicrohttpd
+libmicrohttpd		mono	${LIBMICROHTTPD}/manual/libmicrohttpd.html
+libmicrohttpd		node	${LIBMICROHTTPD}/manual/html_node/
+ microhttpd-tutorial	mono	${LIBMICROHTTPD}/tutorial.html
+
+libtasn1	mono	${GS}/libtasn1/manual/libtasn1.html
+libtasn1	node	${GS}/libtasn1/manual/html_node/
+
+libtool		mono	${GS}/libtool/manual/libtool.html
+libtool		node	${GS}/libtool/manual/html_node/
+
+lightning	mono	${GS}/lightning/manual/lightning.html
+lightning	node	${GS}/lightning/manual/html_node/
+
+# The stable/ url redirects immediately, but that's ok.
+# The .html extension is omitted on their web site, but it works if given.
+LILYPOND = http://lilypond.org/doc/stable/Documentation
+ lilypond-internals	node ${LILYPOND}/internals/
+ lilypond-learning	node ${LILYPOND}/learning/
+ lilypond-notation 	node ${LILYPOND}/notation/
+ lilypond-snippets 	node ${LILYPOND}/snippets/
+ lilypond-usage		node ${LILYPOND}/usage/
+ lilypond-web		node ${LILYPOND}/web/
+ music-glossary		node ${LILYPOND}/music-glossary/
+
+liquidwar6	mono	${GS}/liquidwar6/manual/liquidwar6.html
+liquidwar6	node	${GS}/liquidwar6/manual/html_node/
+
+lispintro	mono	${GS}/emacs/emacs-lisp-intro/html_mono/emacs-lisp-intro.html
+lispintro	node	${GS}/emacs/emacs-lisp-intro/html_node/index.html
+
+LSH = http://www.lysator.liu.se/~nisse/lsh
+  lsh		mono	${LSH}/lsh.html
+
+m4		mono	${GS}/m4/manual/m4.html
+m4		node	${GS}/m4/manual/html_node/
+
+mailutils	mono	${GS}/mailutils/manual/mailutils.html
+mailutils	chapter	${GS}/mailutils/manual/html_chapter/
+mailutils	section	${GS}/mailutils/manual/html_section/
+mailutils	node	${GS}/mailutils/manual/html_node/
+
+make		mono	${GS}/make/manual/make.html
+make		node	${GS}/make/manual/html_node/
+
+mdk		mono	${GS}/mdk/manual/mdk.html
+mdk		node	${GS}/mdk/manual/html_node/
+
+METAEXCHANGE = http://ftp.gwdg.de/pub/gnu2/iwfmdh/doc/texinfo
+ iwf_mh		node	${METAEXCHANGE}/iwf_mh.html
+ scantest	node	${METAEXCHANGE}/scantest.html
+
+MIT_SCHEME = ${GS}/mit-scheme/documentation
+ mit-scheme-ref	  node	${MIT_SCHEME}/mit-scheme-ref/
+ mit-scheme-user  node	${MIT_SCHEME}/mit-scheme-user/
+ sos		  node	${MIT_SCHEME}/mit-scheme-sos/
+ mit-scheme-imail node	${MIT_SCHEME}/mit-scheme-imail/
+
+moe		mono	${GS}/moe/manual/moe_manual.html
+
+motti		node	${GS}/motti/manual/
+
+mpc		node	http://www.multiprecision.org/index.php?prog=mpc&page=html
+
+mpfr		mono	http://www.mpfr.org/mpfr-current/mpfr.html
+
+mtools		mono	${GS}/mtools/manual/mtools.html
+
+myserver	node	http://www.myserverproject.net/documentation/
+
+nano		mono	http://www.nano-editor.org/dist/latest/nano.html
+
+nettle		chapter	http://www.lysator.liu.se/~nisse/nettle/nettle.html
+
+ocrad		mono	${GS}/ocrad/manual/ocrad_manual.html
+
+parted		mono	${GS}/parted/manual/parted.html
+parted		node	${GS}/parted/manual/html_node/
+
+pascal		mono	http://www.gnu-pascal.de/gpc/
+
+# can't use pcb since url's contain dates --30nov10
+
+perl		mono	${GS}/perl/manual/perldoc-all.html
+
+PIES = http://www.gnu.org.ua/software/pies/manual
+pies		mono	${PIES}/pies.html
+pies 		chapter	${PIES}/html_chapter/
+pies 		section	${PIES}/html_section/
+pies		node	${PIES}/html_node/
+
+plotutils	mono	${GS}/plotutils/manual/en/plotutils.html
+plotutils	node	${GS}/plotutils/manual/en/html_node/
+
+proxyknife	mono	${GS}/proxyknife/manual/proxyknife.html
+proxyknife	node	${GS}/proxyknife/manual/html_node/
+
+pspp		mono	${GS}/pspp/manual/pspp.html
+pspp		node	${GS}/pspp/manual/html_node/
+
+pyconfigure	mono	${GS}/pyconfigure/manual/pyconfigure.html
+pyconfigure	node	${GS}/pyconfigure/manual/html_node/
+
+R = http://cran.r-project.org/doc/manuals
+ R-intro	mono	${R}/R-intro.html
+ R-lang		mono	${R}/R-lang.html
+ R-exts		mono	${R}/R-exts.html
+ R-data		mono	${R}/R-data.html
+ R-admin	mono	${R}/R-admin.html
+ R-ints		mono	${R}/R-ints.html
+
+rcs		mono	${GS}/rcs/manual/rcs.html
+rcs		node	${GS}/rcs/manual/html_node/
+
+READLINE = http://cnswww.cns.cwru.edu/php/chet/readline
+readline        mono    ${READLINE}/readline.html
+ rluserman      mono    ${READLINE}/rluserman.html
+ history        mono    ${READLINE}/history.html
+
+recode		mono	http://recode.progiciels-bpi.ca/manual/index.html
+
+recutils	mono	${GS}/recutils/manual/recutils.html
+recutils	node	${GS}/recutils/manual/html_node/
+
+reftex		mono	${GS}/auctex/manual/reftex.html
+reftex		node	${GS}/auctex/manual/reftex/
+
+remotecontrol	mono	${GS}/remotecontrol/manual/remotecontrol.html
+remotecontrol	node	${GS}/remotecontrol/manual/html_node/
+
+rottlog		mono	${GS}/rottlog/manual/rottlog.html
+rottlog		node	${GS}/rottlog/manual/html_node/
+
+RUSH = http://www.gnu.org.ua/software/rush/manual
+rush		mono	${RUSH}/rush.html
+rush 		chapter	${RUSH}/html_chapter/
+rush 		section	${RUSH}/html_section/
+rush		node	${RUSH}/html_node/
+
+screen		mono	${GS}/screen/manual/screen.html
+screen		node	${GS}/screen/manual/html_node/
+
+sed		mono	${GS}/sed/manual/sed.html
+sed		node	${GS}/sed/manual/html_node/
+
+sharutils	mono	${GS}/sharutils/manual/html_mono/sharutils.html
+sharutils	chapter	${GS}/sharutils/manual/html_chapter/
+sharutils	node	${GS}/sharutils/manual/html_node/
+
+shepherd	mono	${GS}/shepherd/manual/shepherd.html
+shepherd	node	${GS}/shepherd/manual/html_node/
+
+# can't use mono files since they have generic names
+SMALLTALK = ${GS}/smalltalk
+smalltalk	node	${SMALLTALK}/manual/html_node/
+ smalltalk-base	node	${SMALLTALK}/manual-base/html_node/
+ smalltalk-libs	node	${SMALLTALK}/manual-libs/html_node/
+
+sourceinstall	mono	${GS}/sourceinstall/manual/sourceinstall.html
+sourceinstall	node	${GS}/sourceinstall/manual/html_node/
+
+sqltutor	mono	${GS}/sqltutor/manual/sqltutor.html
+sqltutor	node	${GS}/sqltutor/manual/html_node/
+
+src-highlite	mono	${GS}/src-highlite/source-highlight.html
+
+swbis		mono	${GS}/swbis/manual.html
+
+tar		mono	${GS}/tar/manual/tar.html
+tar		chapter	${GS}/tar/manual/html_chapter/
+tar		section	${GS}/tar/manual/html_section/
+tar		node	${GS}/autoconf/manual/html_node/
+
+teseq		mono	${GS}/teseq/teseq.html
+teseq		node	${GS}/teseq/html_node/
+
+TEXINFO = ${GS}/texinfo/manual
+texinfo		mono	${TEXINFO}/texinfo/texinfo.html
+texinfo		node	${TEXINFO}/texinfo/html_node/
+ #
+ info		mono	${TEXINFO}/info/info.html
+ info		node	${TEXINFO}/info/html_node/
+ #
+ info-stnd	mono	${TEXINFO}/info-stnd/info-stnd.html
+ info-stnd	node	${TEXINFO}/info-stnd/html_node/
+
+thales		node	${GS}/thales/manual/
+
+units		mono	${GS}/units/manual/units.html
+units		node	${GS}/units/manual/html_node/
+
+vc-dwim		mono	${GS}/vc-dwim/manual/vc-dwim.html
+vc-dwim		node	${GS}/vc-dwim/manual/html_node/
+
+wdiff		mono	${GS}/wdiff/manual/wdiff.html
+wdiff		node	${GS}/wdiff/manual/html_node/
+
+websocket4j	mono	${GS}/websocket4j/manual/websocket4j.html
+websocket4j	node	${GS}/websocket4j/manual/html_node/
+
+wget		mono	${GS}/wget/manual/wget.html
+wget		node	${GS}/wget/manual/html_node/
+
+xboard		mono	${GS}/xboard/manual/xboard.html
+xboard		node	${GS}/xboard/manual/html_node/
+
+# emacs-page
+# Free TeX-related Texinfo manuals on tug.org.
+
+T = http://tug.org/texinfohtml
+
+dvipng		mono	${T}/dvipng.html
+dvips		mono	${T}/dvips.html
+eplain		mono	${T}/eplain.html
+kpathsea	mono	${T}/kpathsea.html
+latex2e		mono	${T}/latex2e.html
+tlbuild		mono	${T}/tlbuild.html
+web2c		mono	${T}/web2c.html
+
+
+# Local Variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "htmlxrefversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/emacs/guix-base.el b/emacs/guix-base.el
index 9f9f258451..1248ecbce5 100644
--- a/emacs/guix-base.el
+++ b/emacs/guix-base.el
@@ -55,6 +55,14 @@
 If it is not set by a user, it is set after starting Guile REPL.
 This directory is used to define location of the packages.")
 
+(defun guix-read-directory ()
+  "Return `guix-directory' or prompt for it.
+This function is intended for using in `interactive' forms."
+  (if current-prefix-arg
+      (read-directory-name "Directory with Guix modules: "
+                           guix-directory)
+    guix-directory))
+
 (defun guix-set-directory ()
   "Set `guix-directory' if needed."
   (or guix-directory
@@ -63,17 +71,17 @@ This directory is used to define location of the packages.")
 
 (add-hook 'guix-after-start-repl-hook 'guix-set-directory)
 
-(defun guix-find-location (location)
+(defun guix-find-location (location &optional directory)
   "Go to LOCATION of a package.
 LOCATION is a string of the form:
 
   \"PATH:LINE:COLUMN\"
 
 If PATH is relative, it is considered to be relative to
-`guix-directory'."
+DIRECTORY (`guix-directory' by default)."
   (cl-multiple-value-bind (path line col)
       (split-string location ":")
-    (let ((file (expand-file-name path guix-directory))
+    (let ((file (expand-file-name path (or directory guix-directory)))
           (line (string-to-number line))
           (col  (string-to-number col)))
       (find-file file)
@@ -113,12 +121,17 @@ See `guix-packages-profile'."
                     (guix-packages-profile profile generation system?)))
 
 ;;;###autoload
-(defun guix-edit (id-or-name)
-  "Edit (go to location of) package with ID-OR-NAME."
-  (interactive (list (guix-read-package-name)))
+(defun guix-edit (id-or-name &optional directory)
+  "Edit (go to location of) package with ID-OR-NAME.
+See `guix-find-location' for the meaning of package location and
+DIRECTORY.
+Interactively, with prefix argument, prompt for DIRECTORY."
+  (interactive
+   (list (guix-read-package-name)
+         (guix-read-directory)))
   (let ((loc (guix-package-location id-or-name)))
     (if loc
-        (guix-find-location loc)
+        (guix-find-location loc directory)
       (message "Couldn't find package location."))))
 
 
diff --git a/emacs/guix-buffer.el b/emacs/guix-buffer.el
index af76e638b6..4cefe9989e 100644
--- a/emacs/guix-buffer.el
+++ b/emacs/guix-buffer.el
@@ -241,8 +241,10 @@ HISTORY should be one of the following:
   `replace' - replace the current history item."
   (guix-buffer-with-item buffer-item
     (when %entries
-      (guix-buffer-show-entries %entries %buffer-type %entry-type)
+      ;; Set buffer item before showing entries, so that its value can
+      ;; be used by the code for displaying entries.
       (setq guix-buffer-item buffer-item)
+      (guix-buffer-show-entries %entries %buffer-type %entry-type)
       (when history
         (funcall (cl-ecase history
                    (add     #'guix-history-add)
diff --git a/emacs/guix-build-log.el b/emacs/guix-build-log.el
index e08a88f6cc..f67be16326 100644
--- a/emacs/guix-build-log.el
+++ b/emacs/guix-build-log.el
@@ -367,6 +367,9 @@ programmatically using hooks:
   (guix-build-log-mode))
 
 ;;;###autoload
+(add-hook 'shell-mode-hook 'guix-build-log-minor-mode-activate-maybe)
+
+;;;###autoload
 (add-to-list 'auto-mode-alist
              ;; Regexp for log files (usually placed in /var/log/guix/...)
              (cons (rx "/guix/drvs/" (= 2 alnum) "/" (= 30 alnum)
diff --git a/emacs/guix-devel.el b/emacs/guix-devel.el
index 8eb030942c..ee8371ce81 100644
--- a/emacs/guix-devel.el
+++ b/emacs/guix-devel.el
@@ -364,6 +364,9 @@ bindings:
   (when guix-devel-activate-mode
     (guix-devel-mode)))
 
+;;;###autoload
+(add-hook 'scheme-mode-hook 'guix-devel-activate-mode-maybe)
+
 
 (defvar guix-devel-emacs-font-lock-keywords
   (eval-when-compile
diff --git a/emacs/guix-init.el b/emacs/guix-init.el
index 47ced6abaa..1d7d258f69 100644
--- a/emacs/guix-init.el
+++ b/emacs/guix-init.el
@@ -1,7 +1,4 @@
 (require 'guix-autoloads)
 (require 'guix-emacs)
 
-(add-hook 'scheme-mode-hook 'guix-devel-activate-mode-maybe)
-(add-hook 'shell-mode-hook 'guix-build-log-minor-mode-activate-maybe)
-
 (provide 'guix-init)
diff --git a/emacs/guix-main.scm b/emacs/guix-main.scm
index 335686ed25..11b9c773b9 100644
--- a/emacs/guix-main.scm
+++ b/emacs/guix-main.scm
@@ -856,9 +856,7 @@ parameter/value pairs."
 
 (define* (package->manifest-entry* package #:optional output)
   (and package
-       (begin
-         (check-package-freshness package)
-         (package->manifest-entry package output))))
+       (package->manifest-entry package output)))
 
 (define* (make-install-manifest-entries id #:optional output)
   (package->manifest-entry* (package-by-id id) output))
diff --git a/emacs/guix-profiles.el b/emacs/guix-profiles.el
index 43ad1d42eb..12cf46dbf8 100644
--- a/emacs/guix-profiles.el
+++ b/emacs/guix-profiles.el
@@ -40,6 +40,14 @@
 (defvar guix-current-profile guix-default-profile
   "Current profile.")
 
+(defvar guix-system-profile-regexp
+  (concat "\\`" (regexp-quote guix-system-profile))
+  "Regexp matching system profiles.")
+
+(defun guix-system-profile? (profile)
+  "Return non-nil, if PROFILE is a system one."
+  (string-match-p guix-system-profile-regexp profile))
+
 (defun guix-profile-prompt (&optional default)
   "Prompt for profile and return it.
 Use DEFAULT as a start directory.  If it is nil, use
diff --git a/emacs/guix-ui-package.el b/emacs/guix-ui-package.el
index 0971fdd438..d6d26335fa 100644
--- a/emacs/guix-ui-package.el
+++ b/emacs/guix-ui-package.el
@@ -454,17 +454,22 @@ current OUTPUT is installed (if there is such output in
                              (string= (guix-entry-value entry 'output)
                                       output))
                            installed))
-         (action-type (if installed-entry 'delete 'install)))
+         (action-type (if installed-entry 'delete 'install))
+         (profile (guix-ui-current-profile)))
     (guix-info-insert-indent)
     (guix-format-insert output
                         (if installed-entry
                             'guix-package-info-installed-outputs
                           'guix-package-info-uninstalled-outputs)
                         guix-package-info-output-format)
-    (guix-package-info-insert-action-button action-type entry output)
-    (when obsolete
-      (guix-info-insert-indent)
-      (guix-package-info-insert-action-button 'upgrade entry output))
+    ;; Do not allow a user to install/delete anything to/from a system
+    ;; profile, so add action buttons only for non-system profiles.
+    (when (and profile
+               (not (guix-system-profile? profile)))
+      (guix-package-info-insert-action-button action-type entry output)
+      (when obsolete
+        (guix-info-insert-indent)
+        (guix-package-info-insert-action-button 'upgrade entry output)))
     (insert "\n")
     (when installed-entry
       (guix-info-insert-entry installed-entry 'installed-output 2))))
@@ -723,10 +728,22 @@ take an entry as argument."
             'upgrade nil
             (guix-package-installed-outputs entry)))))
 
+(defun guix-package-assert-non-system-profile ()
+  "Verify that the current profile is not a system one.
+The current profile is the one used by the current buffer."
+  (let ((profile (guix-ui-current-profile)))
+    (and profile
+         (guix-system-profile? profile)
+         (user-error "Packages cannot be installed or removed to/from \
+profile '%s'.
+Use 'guix system reconfigure' shell command to modify a system profile."
+                     profile))))
+
 (defun guix-package-execute-actions (fun)
   "Perform actions on the marked packages.
 Use FUN to define actions suitable for `guix-process-package-actions'.
 FUN should take action-type as argument."
+  (guix-package-assert-non-system-profile)
   (let ((actions (delq nil
                        (mapcar fun '(install delete upgrade)))))
     (if actions
@@ -746,10 +763,11 @@ The specification is suitable for `guix-process-package-actions'."
   (let ((specs (guix-list-get-marked-args action-type)))
     (and specs (cons action-type specs))))
 
-(defun guix-package-list-edit ()
-  "Go to the location of the current package."
-  (interactive)
-  (guix-edit (guix-list-current-id)))
+(defun guix-package-list-edit (&optional directory)
+  "Go to the location of the current package.
+See `guix-find-location' for the meaning of DIRECTORY."
+  (interactive (list (guix-read-directory)))
+  (guix-edit (guix-list-current-id) directory))
 
 (defun guix-package-list-latest-builds (number &rest args)
   "Display latest NUMBER of Hydra builds of the current package.
@@ -906,11 +924,13 @@ See `guix-package-info-type'."
                  'id (cl-remove-duplicates pids))
        'add))))
 
-(defun guix-output-list-edit ()
-  "Go to the location of the current package."
-  (interactive)
+(defun guix-output-list-edit (&optional directory)
+  "Go to the location of the current package.
+See `guix-find-location' for the meaning of DIRECTORY."
+  (interactive (list (guix-read-directory)))
   (guix-edit (guix-entry-value (guix-list-current-entry)
-                               'package-id)))
+                               'package-id)
+             directory))
 
 
 ;;; Interactive commands
@@ -979,6 +999,19 @@ Interactively with prefix, prompt for PROFILE."
   (guix-package-get-display profile 'installed))
 
 ;;;###autoload
+(defun guix-installed-user-packages ()
+  "Display information about Guix packages installed in a user profile."
+  (interactive)
+  (guix-installed-packages guix-user-profile))
+
+;;;###autoload
+(defun guix-installed-system-packages ()
+  "Display information about Guix packages installed in a system profile."
+  (interactive)
+  (guix-installed-packages
+   (guix-packages-profile guix-system-profile nil t)))
+
+;;;###autoload
 (defun guix-obsolete-packages (&optional profile)
   "Display information about obsolete Guix packages.
 If PROFILE is nil, use `guix-current-profile'.
diff --git a/gnu-system.am b/gnu-system.am
index 4d32e596b4..6ccca125ce 100644
--- a/gnu-system.am
+++ b/gnu-system.am
@@ -42,6 +42,7 @@ GNU_SYSTEM_MODULES =				\
   gnu/packages/attr.scm				\
   gnu/packages/audacity.scm			\
   gnu/packages/audio.scm			\
+  gnu/packages/augeas.scm			\
   gnu/packages/autogen.scm			\
   gnu/packages/autotools.scm			\
   gnu/packages/avahi.scm			\
@@ -171,7 +172,6 @@ GNU_SYSTEM_MODULES =				\
   gnu/packages/jemalloc.scm			\
   gnu/packages/jrnl.scm				\
   gnu/packages/julia.scm			\
-  gnu/packages/kde.scm				\
   gnu/packages/kde-frameworks.scm		\
   gnu/packages/key-mon.scm			\
   gnu/packages/kodi.scm				\
@@ -215,6 +215,7 @@ GNU_SYSTEM_MODULES =				\
   gnu/packages/mail.scm				\
   gnu/packages/make-bootstrap.scm		\
   gnu/packages/markdown.scm			\
+  gnu/packages/mate.scm             \
   gnu/packages/maths.scm			\
   gnu/packages/mc.scm				\
   gnu/packages/mcrypt.scm			\
@@ -435,6 +436,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/clucene-pkgconfig.patch			\
   gnu/packages/patches/cmake-fix-tests.patch			\
   gnu/packages/patches/cpio-gets-undeclared.patch		\
+  gnu/packages/patches/cpio-CVE-2016-2037.patch			\
   gnu/packages/patches/cpufrequtils-fix-aclocal.patch		\
   gnu/packages/patches/crda-optional-gcrypt.patch		\
   gnu/packages/patches/crossmap-allow-system-pysam.patch	\
@@ -489,6 +491,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/glib-tests-prlimit.patch			\
   gnu/packages/patches/glib-tests-timer.patch			\
   gnu/packages/patches/glib-tests-gapplication.patch		\
+  gnu/packages/patches/glibc-CVE-2015-7547.patch		\
   gnu/packages/patches/glibc-bootstrap-system.patch		\
   gnu/packages/patches/glibc-hurd-extern-inline.patch		\
   gnu/packages/patches/glibc-ldd-x86_64.patch			\
@@ -499,6 +502,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/gmp-arm-asm-nothumb.patch		\
   gnu/packages/patches/gmp-faulty-test.patch			\
   gnu/packages/patches/gnucash-price-quotes-perl.patch		\
+  gnu/packages/patches/gnupg-simple-query-ignore-status-messages.patch \
   gnu/packages/patches/gobject-introspection-absolute-shlib-path.patch \
   gnu/packages/patches/gobject-introspection-cc.patch		\
   gnu/packages/patches/gobject-introspection-girepository.patch	\
@@ -521,6 +525,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/hydra-automake-1.15.patch		\
   gnu/packages/patches/hydra-disable-darcs-test.patch		\
   gnu/packages/patches/icecat-avoid-bundled-includes.patch	\
+  gnu/packages/patches/icecat-update-graphite2.patch		\
   gnu/packages/patches/icecat-re-enable-DHE-cipher-suites.patch	\
   gnu/packages/patches/icu4c-CVE-2014-6585.patch		\
   gnu/packages/patches/icu4c-CVE-2015-1270.patch		\
@@ -561,14 +566,12 @@ dist_patch_DATA =						\
   gnu/packages/patches/libmad-armv7-thumb-pt2.patch		\
   gnu/packages/patches/libmad-frame-length.patch		\
   gnu/packages/patches/libmad-mips-newgcc.patch			\
+  gnu/packages/patches/libssh-0.6.5-CVE-2016-0739.patch		\
   gnu/packages/patches/libtheora-config-guess.patch		\
   gnu/packages/patches/libtiff-CVE-2015-8665+CVE-2015-8683.patch \
   gnu/packages/patches/libtiff-oob-accesses-in-decode.patch	\
   gnu/packages/patches/libtiff-oob-write-in-nextdecode.patch	\
   gnu/packages/patches/libtool-skip-tests2.patch		\
-  gnu/packages/patches/libsndfile-CVE-2014-9496.patch		\
-  gnu/packages/patches/libsndfile-CVE-2015-7805.patch		\
-  gnu/packages/patches/libssh-CVE-2014-0017.patch		\
   gnu/packages/patches/libunwind-CVE-2015-3239.patch		\
   gnu/packages/patches/libwmf-CAN-2004-0941.patch		\
   gnu/packages/patches/libwmf-CVE-2006-3376.patch		\
@@ -602,12 +605,10 @@ dist_patch_DATA =						\
   gnu/packages/patches/mcron-install.patch			\
   gnu/packages/patches/mdadm-gcc-4.9-fix.patch			\
   gnu/packages/patches/mhash-keygen-test-segfault.patch		\
-  gnu/packages/patches/mit-krb5-CVE-2015-2695-pt1.patch		\
-  gnu/packages/patches/mit-krb5-CVE-2015-2695-pt2.patch		\
-  gnu/packages/patches/mit-krb5-CVE-2015-2696.patch		\
-  gnu/packages/patches/mit-krb5-CVE-2015-2697.patch		\
-  gnu/packages/patches/mit-krb5-CVE-2015-2698-pt1.patch		\
-  gnu/packages/patches/mit-krb5-CVE-2015-2698-pt2.patch		\
+  gnu/packages/patches/mit-krb5-CVE-2015-8629.patch		\
+  gnu/packages/patches/mit-krb5-CVE-2015-8630.patch		\
+  gnu/packages/patches/mit-krb5-CVE-2015-8631.patch		\
+  gnu/packages/patches/mit-krb5-init-context-null-spnego.patch	\
   gnu/packages/patches/mpc123-initialize-ao.patch		\
   gnu/packages/patches/mplayer2-theora-fix.patch		\
   gnu/packages/patches/module-init-tools-moduledir.patch	\
@@ -624,6 +625,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/nvi-assume-preserve-path.patch		\
   gnu/packages/patches/nvi-dbpagesize-binpower.patch		\
   gnu/packages/patches/nvi-db4.patch				\
+  gnu/packages/patches/ocaml-findlib-make-install.patch	\
   gnu/packages/patches/openexr-missing-samples.patch		\
   gnu/packages/patches/openimageio-boost-1.60.patch		\
   gnu/packages/patches/openjpeg-CVE-2015-6581.patch		\
@@ -677,14 +679,20 @@ dist_patch_DATA =						\
   gnu/packages/patches/python-ipython-inputhook-ctype.patch	\
   gnu/packages/patches/python2-rdflib-drop-sparqlwrapper.patch	\
   gnu/packages/patches/python-configobj-setuptools.patch	\
+  gnu/packages/patches/python-paste-remove-website-test.patch	\
+  gnu/packages/patches/python-paste-remove-timing-test.patch	\
   gnu/packages/patches/python2-pygobject-2-gi-info-type-error-domain.patch \
   gnu/packages/patches/qemu-CVE-2015-8558.patch			\
   gnu/packages/patches/qemu-CVE-2015-8567.patch			\
   gnu/packages/patches/qemu-CVE-2015-8613.patch			\
+  gnu/packages/patches/qemu-CVE-2015-8619.patch			\
   gnu/packages/patches/qemu-CVE-2015-8701.patch			\
   gnu/packages/patches/qemu-CVE-2015-8743.patch			\
   gnu/packages/patches/qemu-CVE-2016-1568.patch			\
   gnu/packages/patches/qemu-CVE-2016-1922.patch			\
+  gnu/packages/patches/qemu-CVE-2016-1981.patch			\
+  gnu/packages/patches/qemu-CVE-2016-2197.patch			\
+  gnu/packages/patches/qemu-usb-ehci-oob-read.patch		\
   gnu/packages/patches/qemu-virtio-9p-use-accessor-to-get-thread-pool.patch \
   gnu/packages/patches/qt4-ldflags.patch			\
   gnu/packages/patches/ratpoison-shell.patch			\
@@ -701,6 +709,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/slim-session.patch			\
   gnu/packages/patches/slim-config.patch			\
   gnu/packages/patches/slim-sigusr1.patch			\
+  gnu/packages/patches/slurm-configure-remove-nonfree-contribs.patch \
   gnu/packages/patches/soprano-find-clucene.patch		\
   gnu/packages/patches/sudo-CVE-2015-5602.patch			\
   gnu/packages/patches/superlu-dist-scotchmetis.patch		\
@@ -708,6 +717,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/tar-d_ino_in_dirent-fix.patch		\
   gnu/packages/patches/tar-skip-unreliable-tests.patch		\
   gnu/packages/patches/tcl-mkindex-deterministic.patch		\
+  gnu/packages/patches/tclxml-3.2-install.patch			\
   gnu/packages/patches/tcsh-fix-autotest.patch			\
   gnu/packages/patches/texi2html-document-encoding.patch	\
   gnu/packages/patches/texi2html-i18n.patch			\
@@ -763,17 +773,9 @@ dist_patch_DATA =						\
   gnu/packages/patches/xf86-video-intel-compat-api.patch	\
   gnu/packages/patches/xf86-video-intel-glibc-2.20.patch	\
   gnu/packages/patches/xf86-video-mach64-glibc-2.20.patch	\
-  gnu/packages/patches/xf86-video-mga-glibc-2.20.patch		\
   gnu/packages/patches/xf86-video-nv-remove-mibstore.patch	\
   gnu/packages/patches/xf86-video-openchrome-glibc-2.20.patch	\
-  gnu/packages/patches/xf86-video-r128-glibc-2.20.patch		\
-  gnu/packages/patches/xf86-video-siliconmotion-remove-mibstore.patch \
-  gnu/packages/patches/xf86-video-sis-fix-exa-crash.patch	\
-  gnu/packages/patches/xf86-video-sis-update-api.patch		\
-  gnu/packages/patches/xf86-video-tdfx-remove-mibstore.patch	\
   gnu/packages/patches/xf86-video-tga-remove-mibstore.patch	\
-  gnu/packages/patches/xf86-video-trident-remove-mibstore.patch	\
-  gnu/packages/patches/xf86-video-vmware-glibc-2.20.patch	\
   gnu/packages/patches/xfce4-panel-plugins.patch		\
   gnu/packages/patches/xfce4-session-fix-xflock4.patch		\
   gnu/packages/patches/xfce4-settings-defaults.patch		\
diff --git a/gnu/build/linux-modules.scm b/gnu/build/linux-modules.scm
index bbe1a74d85..d7feb3a080 100644
--- a/gnu/build/linux-modules.scm
+++ b/gnu/build/linux-modules.scm
@@ -96,10 +96,20 @@ contains module names, not actual file names."
       name
       (dot-ko name)))
 
+(define (normalize-module-name module)
+  "Return the \"canonical\" name for MODULE, replacing hyphens with
+underscores."
+  ;; See 'modname_normalize' in libkmod.
+  (string-map (lambda (chr)
+                (case chr
+                  ((#\-) #\_)
+                  (else chr)))
+              module))
+
 (define (file-name->module-name file)
-  "Return the module name corresponding to FILE, stripping the trailing '.ko',
-etc."
-  (basename file ".ko"))
+  "Return the module name corresponding to FILE, stripping the trailing '.ko'
+and normalizing it."
+  (normalize-module-name (basename file ".ko")))
 
 (define* (recursive-module-dependencies files
                                         #:key (lookup-module dot-ko))
@@ -138,7 +148,9 @@ LOOKUP-MODULE to the module name."
 (define (module-black-list)
   "Return the black list of modules that must not be loaded.  This black list
 is specified using 'modprobe.blacklist=MODULE1,MODULE2,...' on the kernel
-command line; it is honored by libkmod."
+command line; it is honored by libkmod for users that pass
+'KMOD_PROBE_APPLY_BLACKLIST', which includes 'modprobe --use-blacklist' and
+udev."
   (define parameter
     "modprobe.blacklist=")
 
diff --git a/gnu/build/vm.scm b/gnu/build/vm.scm
index a095f9de8a..48e701adbe 100644
--- a/gnu/build/vm.scm
+++ b/gnu/build/vm.scm
@@ -1,5 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
+;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -97,7 +99,7 @@ the #:references-graphs parameter of 'derivation'."
     (_ #f))
 
   (unless (zero?
-           (apply system* qemu "-enable-kvm" "-nographic" "-no-reboot"
+           (apply system* qemu "-nographic" "-no-reboot"
                   "-m" (number->string memory-size)
                   "-net" "nic,model=virtio"
                   "-virtfs"
@@ -111,10 +113,17 @@ the #:references-graphs parameter of 'derivation'."
                   "-initrd" initrd
                   "-append" (string-append "console=ttyS0 --load="
                                            builder)
-                  (if make-disk-image?
-                      `("-drive" ,(string-append "file=" image-file
-                                                 ",if=virtio"))
-                      '())))
+                  (append
+                   (if make-disk-image?
+                       `("-drive" ,(string-append "file=" image-file
+                                                  ",if=virtio"))
+                       '())
+                   ;; Only enable kvm if we see /dev/kvm exists.
+                   ;; This allows users without hardware virtualization to still
+                   ;; use these commands.
+                   (if (file-exists? "/dev/kvm")
+                       '("-enable-kvm")
+                       '()))))
     (error "qemu failed" qemu))
 
   (if make-disk-image?
diff --git a/gnu/packages.scm b/gnu/packages.scm
index b309a7806d..64a695d970 100644
--- a/gnu/packages.scm
+++ b/gnu/packages.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2013 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2016 Alex Kost <alezost@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,9 +23,6 @@
   #:use-module (guix packages)
   #:use-module (guix ui)
   #:use-module (guix utils)
-  #:use-module ((guix ftp-client) #:select (ftp-open))
-  #:use-module (guix gnu-maintenance)
-  #:use-module (guix upstream)
   #:use-module (ice-9 ftw)
   #:use-module (ice-9 vlist)
   #:use-module (ice-9 match)
@@ -46,8 +44,6 @@
             find-best-packages-by-name
             find-newest-available-packages
 
-            check-package-freshness
-
             specification->package
             specification->package+output))
 
@@ -280,69 +276,6 @@ return its return value."
                     (lambda (k signum)
                       (handler signum))))
 
-(define-syntax-rule (waiting exp fmt rest ...)
-  "Display the given message while EXP is being evaluated."
-  (let* ((message (format #f fmt rest ...))
-         (blank   (make-string (string-length message) #\space)))
-    (display message (current-error-port))
-    (force-output (current-error-port))
-    (call-with-sigint-handler
-     (lambda ()
-       (dynamic-wind
-         (const #f)
-         (lambda () exp)
-         (lambda ()
-           ;; Clear the line.
-           (display #\cr (current-error-port))
-           (display blank (current-error-port))
-           (display #\cr (current-error-port))
-           (force-output (current-error-port)))))
-     (lambda (signum)
-       (format (current-error-port) "  interrupted by signal ~a~%" SIGINT)
-       #f))))
-
-(define ftp-open*
-  ;; Memoizing version of `ftp-open'.  The goal is to avoid initiating a new
-  ;; FTP connection for each package, esp. since most of them are to the same
-  ;; server.  This has a noticeable impact when doing "guix upgrade -u".
-  (memoize ftp-open))
-
-(define (check-package-freshness package)
-  "Check whether PACKAGE has a newer version available upstream, and report
-it."
-  ;; TODO: Automatically inject the upstream version when desired.
-
-  (catch #t
-    (lambda ()
-      (when (false-if-exception (gnu-package? package))
-        (let ((name      (package-name package))
-              (full-name (package-full-name package)))
-          ;; XXX: This could work with non-GNU packages as well.  However,
-          ;; GNU's FTP-based updater would be too slow if it weren't memoized,
-          ;; and the generic interface in (guix upstream) doesn't support
-          ;; that.
-          (match (waiting (latest-release name
-                                          #:ftp-open ftp-open*
-                                          #:ftp-close (const #f))
-                          (_ "looking for the latest release of GNU ~a...") name)
-            ((? upstream-source? source)
-             (let ((latest-version
-                    (string-append (upstream-source-package source) "-"
-                                   (upstream-source-version source))))
-              (when (version>? latest-version full-name)
-                (format (current-error-port)
-                        (_ "~a: note: using ~a \
-but ~a is available upstream~%")
-                        (location->string (package-location package))
-                        full-name latest-version))))
-            (_ #t)))))
-    (lambda (key . args)
-      ;; Silently ignore networking errors rather than preventing
-      ;; installation.
-      (case key
-        ((getaddrinfo-error ftp-error) #f)
-        (else (apply throw key args))))))
-
 (define (specification->package spec)
   "Return a package matching SPEC.  SPEC may be a package name, or a package
 name followed by a hyphen and a version number.  If the version number is not
diff --git a/gnu/packages/abduco.scm b/gnu/packages/abduco.scm
index 79865f2211..ae67f81849 100644
--- a/gnu/packages/abduco.scm
+++ b/gnu/packages/abduco.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015 Leo Famulari <leo@famulari.name>
+;;; Copyright © 2015, 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -25,14 +25,15 @@
 (define-public abduco
   (package
    (name "abduco")
-   (version "0.4")
+   (version "0.5")
    (source (origin
             (method url-fetch)
             (uri (string-append
                   "http://www.brain-dump.org/projects/abduco/abduco-"
                   version ".tar.gz"))
             (sha256
-             (base32 "1fxwg2s5w183p0rwzsxizy9jdnilv5qqs647l3wl3khny6fp58xx"))))
+             (base32
+              "11phry5wnvwm9ckij5gxbrjfgdz3x38vpnm505q5ldc88im248mz"))))
    (build-system gnu-build-system)
    (arguments
     `(#:make-flags (list "CC=gcc"
diff --git a/gnu/packages/admin.scm b/gnu/packages/admin.scm
index eca4d9208f..b0b2046d2e 100644
--- a/gnu/packages/admin.scm
+++ b/gnu/packages/admin.scm
@@ -7,6 +7,8 @@
 ;;; Copyright © 2015 Alex Sassmannshausen <alex.sassmannshausen@gmail.com>
 ;;; Copyright © 2015 Eric Dvorsak <eric@dvorsak.fr>
 ;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
+;;; Copyright © 2016 Pjotr Prins <pjotr.guix@thebird.nl>
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -35,6 +37,7 @@
   #:use-module (guix build-system trivial)
   #:use-module (gnu packages)
   #:use-module (gnu packages base)
+  #:use-module (gnu packages cyrus-sasl)
   #:use-module (gnu packages ncurses)
   #:use-module (gnu packages readline)
   #:use-module (gnu packages linux)
@@ -48,6 +51,7 @@
   #:use-module (gnu packages bison)
   #:use-module (gnu packages flex)
   #:use-module (gnu packages glib)
+  #:use-module (gnu packages openldap)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages popt)
   #:use-module (gnu packages texinfo)
@@ -81,8 +85,8 @@
                          ;; is used by a bunch of services.
                          (method url-fetch)
                          (uri (string-append
-                               "http://git.savannah.gnu.org/cgit/dmd.git/patch/"
-                               "?id=d1d0ff30b3ed2b86b0a3c9bc048d2a855f8e31e6"))
+                               "http://git.savannah.gnu.org/cgit/shepherd.git/"
+                               "patch?id=d1d0ff30b3ed2b86b0a3c9bc048d2a855f8e31e6"))
                          (sha256
                           (base32
                            "1lqymypixfiyb72d6bn24m06ry2q1ljnnv0qrc89pbb4z9azaa4d"))
@@ -152,14 +156,14 @@ graphs and can export its output to different formats.")
 (define-public htop
   (package
    (name "htop")
-   (version "1.0.3")
+   (version "2.0.0")
    (source (origin
             (method url-fetch)
             (uri (string-append "http://hisham.hm/htop/releases/"
                   version "/htop-" version ".tar.gz"))
             (sha256
              (base32
-              "0a8qbpsifzjwc4f45xfwm48jhm59g6q5hlib4bf7z13mgy95fp05"))))
+              "1d944hn0ldxvxfrz9acr26lpmzlwj91m0s7x2xnivnfnmfha4p6i"))))
    (build-system gnu-build-system)
    (inputs
     `(("ncurses" ,ncurses)))
@@ -1426,4 +1430,69 @@ frequently used directories by typing only a small pattern.")
 for CPU usage.  It listens to network traffic on a named interface and
 displays a table of current bandwidth usage by pairs of hosts.")
     (home-page "http://www.ex-parrot.com/~pdw/iftop/")
-    (license license:gpl3)))
+    (license license:gpl2+)))
+
+(define-public munge
+  (package
+    (name "munge")
+    (version "0.5.11")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://github.com/dun/munge/archive/munge-"
+                                  version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0njplyalwwqh7xr7xc7klc6x06mq0ak8w2pxh85w8n4hxkmqqnf5"))))
+    (inputs
+     `(("openssl" ,openssl)
+       ("libgcrypt" ,libgcrypt)))
+    (build-system gnu-build-system)
+    (home-page "http://dun.github.io/munge/")
+    (synopsis "Cluster computing authentication service")
+    (description
+     "Munge is an authentication service for creating and validating
+credentials.  It allows a process to authenticate the UID and GID of another
+local or remote process within a group of hosts having common users and
+groups.  These hosts form a security realm that is defined by a shared
+cryptographic key.  Clients within this security realm can create and validate
+credentials without the use of root privileges, reserved ports, or
+platform-specific methods.")
+    (license license:gpl3+)))
+
+(define-public audit
+  (package
+    (name "audit")
+    (version "2.4.5")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://people.redhat.com/sgrubb/audit/"
+                                  "audit-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1q1q51dvxscbi4kbakmd4bn0xrvwwaiwvaya79925cbrqwzxsg77"))))
+    (build-system gnu-build-system)
+    (home-page "http://people.redhat.com/sgrubb/audit/")
+    (arguments
+     `(#:configure-flags (list "--with-python=no")
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'fix-tests
+           (lambda _
+             ;; In the build environmnte /etc/passwd does not contain an entry
+             ;; for root/0, so we have to patch the expected value.
+             (substitute* "auparse/test/auparse_test.ref"
+               (("=0 \\(root\\)") "=0 (unknown(0))"))
+             #t)))))
+    (inputs
+     `(("openldap" ,openldap)
+       ("openssl" ,openssl)
+       ("sasl" ,cyrus-sasl)))
+    (synopsis "User-space component to the Linux auditing system")
+    (description
+     "auditd is the user-space component to the Linux auditing system, which
+allows logging of system calls made by user-land processes.  It's responsible
+for writing audit records to the disk.  Viewing the logs is done with the
+@code{ausearch} or @code{aureport} utilities.  Configuring the audit rules is
+done with the @code{auditctl} utility.")
+    (license license:gpl2+)))
diff --git a/gnu/packages/adns.scm b/gnu/packages/adns.scm
index 1af735b6eb..a6fbc1add8 100644
--- a/gnu/packages/adns.scm
+++ b/gnu/packages/adns.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 Ludovic Courtès <ludo@gnu.org>
-;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -59,7 +59,7 @@ scripts.")
 (define-public c-ares
   (package
     (name "c-ares")
-    (version "1.10.0")
+    (version "1.11.0")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -67,7 +67,7 @@ scripts.")
                     ".tar.gz"))
               (sha256
                (base32
-                "1nyka87yf2jfd0y6sspll0yxwb8zi7kyvajrdbjmh4axc5s1cw1x"))))
+                "1z9y1f835dpi1ka2a2vzjygm3djdvr01036ml4l2js6r2xk2wqdk"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
diff --git a/gnu/packages/aidc.scm b/gnu/packages/aidc.scm
index 3ef5d28fbb..32093265a9 100644
--- a/gnu/packages/aidc.scm
+++ b/gnu/packages/aidc.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 John Darringon <jmd@gnu.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -49,14 +50,15 @@ formats.")
 (define-public qrencode
   (package
     (name "qrencode")
-    (version "3.4.3")
+    (version "3.4.4")
     (source (origin
               (method url-fetch)
               (uri (string-append
-                    "http://fukuchi.org/works/qrencode/qrencode-" version
-                    ".tar.bz2"))
-              (sha256 (base32
-                       "163sb580p570p27imc6jhkfdw15kzp8vy1jq92nip1rwa63i9myz"))))
+                    "https://fukuchi.org/works/qrencode/qrencode-" version
+                    ".tar.gz"))
+              (sha256
+               (base32
+                "0wiagx7i8p9zal53smf5abrnh9lr31mv0p36wg017401jrmf5577"))))
     (build-system gnu-build-system)
     (inputs `(("libpng" ,libpng)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -66,4 +68,4 @@ symbol, a kind of 2D symbology that can be scanned by handy terminals such as
 a mobile phone with CCD.  The capacity of QR Code is up to 7000 digits or 4000
 characters, and is highly robust.")
     (license license:lgpl2.1+)
-    (home-page "http://fukuchi.org/works/qrencode")))
+    (home-page "https://fukuchi.org/works/qrencode")))
diff --git a/gnu/packages/algebra.scm b/gnu/packages/algebra.scm
index 0f17403868..85ec61c1b1 100644
--- a/gnu/packages/algebra.scm
+++ b/gnu/packages/algebra.scm
@@ -26,6 +26,7 @@
   #:use-module (gnu packages perl)
   #:use-module (gnu packages readline)
   #:use-module (gnu packages flex)
+  #:use-module (gnu packages texlive)
   #:use-module (gnu packages xorg)
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix packages)
@@ -125,12 +126,13 @@ solve the shortest vector problem.")
               (base32
                 "0c8l83a0gjq73r9hndsrzkypwxvnnm4pxkkzbg6jm95m80nzwh11"))))
    (build-system gnu-build-system)
+   (native-inputs `(("texlive" ,texlive-minimal)))
    (inputs `(("gmp" ,gmp)
              ("libx11" ,libx11)
              ("perl" ,perl)
              ("readline" ,readline)))
    (arguments
-    '(#:make-flags '("gp")
+    '(#:make-flags '("all")
       ;; FIXME: building the documentation requires tex; once this is
       ;; available, replace "gp" by "all"
       #:test-target "dobench"
diff --git a/gnu/packages/audio.scm b/gnu/packages/audio.scm
index 7f0d87ddf7..865394a726 100644
--- a/gnu/packages/audio.scm
+++ b/gnu/packages/audio.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; 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 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
@@ -30,6 +30,7 @@
   #:use-module (guix build-system waf)
   #:use-module (guix build-system trivial)
   #:use-module (guix build-system cmake)
+  #:use-module (guix build-system python)
   #:use-module (gnu packages)
   #:use-module (gnu packages algebra)
   #:use-module (gnu packages autotools)
@@ -158,24 +159,24 @@ streams from live audio.")
 (define-public ardour
   (package
     (name "ardour")
-    (version "4.4")
+    (version "4.7")
     (source (origin
               (method git-fetch)
               (uri (git-reference
                     (url "git://git.ardour.org/ardour/ardour.git")
                     (commit version)))
               (snippet
-               ;; Ardour expects this file to exist at build time.  It can be
-               ;; created from a git checkout with:
-               ;;   ./waf create_stored_revision
+               ;; Ardour expects this file to exist at build time.  The revision
+               ;; is the output of
+               ;;    git describe HEAD | sed 's/^[A-Za-z]*+//'
                '(call-with-output-file
                     "libs/ardour/revision.cc"
                   (lambda (port)
                     (format port "#include \"ardour/revision.h\"
-namespace ARDOUR { const char* revision = \"4.4-210-ga4daf93\" ; }"))))
+namespace ARDOUR { const char* revision = \"4.7-219-g0e36f8e\" ; }"))))
               (sha256
                (base32
-                "1gnrcnq2ksnh7fsa301v1c4p5dqrbqpjylf02rg3za3ab58wxi7l"))
+                "149gswphz77m3pkzsn2nqbm6yvcfa3fva560bcvjzlgb73f64q5l"))
               (file-name (string-append name "-" version))))
     (build-system waf-build-system)
     (arguments
@@ -946,6 +947,34 @@ essential distortions.")
 implementation of the Open Sound Control (OSC) protocol.")
     (license license:lgpl2.1+)))
 
+(define-public python-pyliblo
+  (package
+    (name "python-pyliblo")
+    (version "0.10.0")
+    (source (origin
+             (method url-fetch)
+             (uri (string-append "http://das.nasophon.de/download/pyliblo-"
+                                 version ".tar.gz"))
+             (sha256
+              (base32
+               "13vry6xhxm7adnbyj28w1kpwrh0kf7nw83cz1yq74wl21faz2rzw"))))
+    (build-system python-build-system)
+    (arguments `(#:tests? #f)) ;no tests
+    (inputs
+     `(("python-cython" ,python-cython)
+       ("liblo" ,liblo)))
+    (home-page "http://das.nasophon.de/pyliblo/")
+    (synopsis "Python bindings for liblo")
+    (description
+     "Pyliblo is a Python wrapper for the liblo Open Sound Control (OSC)
+library.  It supports almost the complete functionality of liblo, allowing you
+to send and receive OSC messages using a nice and simple Python API.  Also
+included are the command line utilities @code{send_osc} and @code{dump_osc}.")
+    (license license:lgpl2.1+)))
+
+(define-public python2-pyliblo
+  (package-with-python2 python-pyliblo))
+
 (define-public lilv
   (package
     (name "lilv")
@@ -2032,4 +2061,5 @@ utility.  File formats are abstracted from its core, so it can process any file
 that contains WAVE data, compressed or not---provided there exists a format
 module to handle that particular file type.")
     (home-page "http://etree.org/shnutils/shntool/")
-    (license license:gpl3+)))
+    ;; 'install-sh' bears the x11 license
+    (license (list license:gpl2+ license:x11))))
diff --git a/gnu/packages/augeas.scm b/gnu/packages/augeas.scm
new file mode 100644
index 0000000000..95b96ca25c
--- /dev/null
+++ b/gnu/packages/augeas.scm
@@ -0,0 +1,59 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
+;;;
+;;; 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 augeas)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (guix packages)
+  #:use-module (guix download)
+  #:use-module (guix utils)
+  #:use-module (guix build-system gnu)
+  #:use-module (gnu packages)
+  #:use-module (gnu packages readline)
+  #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages xml))
+
+(define-public augeas
+  (package
+    (name "augeas")
+    (version "1.4.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://download.augeas.net/augeas-"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "0c2vncn0afmgwggnqa5s5z7m3zbcc66bi8v9m1h9w0i9q9xax7v5"))))
+    (build-system gnu-build-system)
+    ;; Marked as "required" in augeas.pc
+    (propagated-inputs
+     `(("libxml2" ,libxml2)))
+    (inputs
+     `(("readline" ,readline)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (home-page "http://augeas.net/")
+    (synopsis "Edit configuration files programmatically")
+    (description
+     "Augeas is a library and command line tool for programmatically editing
+configuration files in a controlled manner.  Augeas exposes a tree of all
+configuration settings and a simple local API for manipulating the tree.
+Augeas then modifies underlying configuration files according to the changes
+that have been made to the tree; it does as little modeling of configurations
+as possible, and focuses exclusivley on transforming the tree-oriented syntax
+of its public API to the myriad syntaxes of individual configuration files.")
+    (license license:lgpl2.1+)))
diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm
index 0b07ea196d..3c6b189120 100644
--- a/gnu/packages/base.scm
+++ b/gnu/packages/base.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2012 Nikita Karetnikov <nikita@karetnikov.org>
-;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014 Alex Kost <alezost@gmail.com>
 ;;; Copyright © 2014, 2015 Manolis Fragkiskos Ragkousis <manolis837@gmail.com>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
@@ -173,7 +173,7 @@ standard utility.")
                 "16d2r9kpivaak948mxzc0bai45mqfw73m113wrkmbffnalv1b5gx"))
               (patches (list (search-patch "patch-hurd-path-max.patch")))))
    (build-system gnu-build-system)
-   (native-inputs `(("ed", ed)))
+   (native-inputs `(("ed" ,ed)))
    (synopsis "Apply differences to originals, with optional backups")
    (description
     "Patch is a program that applies changes to files based on differences
@@ -318,7 +318,7 @@ functionality beyond that which is outlined in the POSIX standard.")
               "19gwwhik3wdwn0r42b7xcihkbxvjl9r2bdal8nifc3k5i4rn3iqb"))
             (patches (list (search-patch "make-impure-dirs.patch")))))
    (build-system gnu-build-system)
-   (native-inputs `(("pkg-config", pkg-config)))  ; to detect Guile
+   (native-inputs `(("pkg-config" ,pkg-config)))  ; to detect Guile
    (inputs `(("guile" ,guile-2.0)))
    (outputs '("out" "debug"))
    (arguments
@@ -479,7 +479,8 @@ store.")
                           '("glibc-ldd-x86_64.patch"
                             "glibc-locale-incompatibility.patch"
                             "glibc-versioned-locpath.patch"
-                            "glibc-o-largefile.patch")))))
+                            "glibc-o-largefile.patch"
+                            "glibc-CVE-2015-7547.patch")))))
    (build-system gnu-build-system)
 
    ;; Glibc's <limits.h> refers to <linux/limit.h>, for instance, so glibc
diff --git a/gnu/packages/bioinformatics.scm b/gnu/packages/bioinformatics.scm
index e277f890a1..7b3838d36f 100644
--- a/gnu/packages/bioinformatics.scm
+++ b/gnu/packages/bioinformatics.scm
@@ -1,3 +1,4 @@
+
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015, 2016 Ben Woodcroft <donttrustben@gmail.com>
@@ -39,6 +40,8 @@
   #:use-module (gnu packages boost)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages cpio)
+  #:use-module (gnu packages curl)
+  #:use-module (gnu packages doxygen)
   #:use-module (gnu packages file)
   #:use-module (gnu packages gawk)
   #:use-module (gnu packages gcc)
@@ -1080,6 +1083,52 @@ preparation protocols.")
 other types of unwanted sequence from high-throughput sequencing reads.")
     (license license:expat)))
 
+(define-public libbigwig
+  (package
+    (name "libbigwig")
+    (version "0.1.4")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://github.com/dpryan79/libBigWig/"
+                                  "archive/" version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "098rjh35pi4a9q83n8wiwvyzykjqj6l8q189p1xgfw4ghywdlvw1"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:test-target "test"
+       #:make-flags
+       (list "CC=gcc"
+             (string-append "prefix=" (assoc-ref %outputs "out")))
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)
+         (add-before 'check 'disable-curl-test
+           (lambda _
+             (substitute* "Makefile"
+               (("./test/testRemote.*") ""))
+             #t))
+         ;; This has been fixed with the upstream commit 4ff6959cd8a0, but
+         ;; there has not yet been a release containing this change.
+         (add-before 'install 'create-target-dirs
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let ((out (assoc-ref outputs "out")))
+               (mkdir-p (string-append out "/lib"))
+               (mkdir-p (string-append out "/include"))
+               #t))))))
+    (inputs
+     `(("zlib" ,zlib)
+       ("curl" ,curl)))
+    (native-inputs
+     `(("doxygen" ,doxygen)))
+    (home-page "https://github.com/dpryan79/libBigWig")
+    (synopsis "C library for handling bigWig files")
+    (description
+     "This package provides a C library for parsing local and remote BigWig
+files.")
+    (license license:expat)))
+
 (define-public deeptools
   (package
     (name "deeptools")
@@ -1741,7 +1790,7 @@ particular, reads spanning multiple exons.")
                (base32
                 "0djmgc0pfli0jilfx8hql1axhwhqxqb8rxg2r5rg07aw73sfs5nx"))))
     (build-system gnu-build-system)
-    (native-inputs `(("perl", perl)))
+    (native-inputs `(("perl" ,perl)))
     (home-page "http://hmmer.janelia.org")
     (synopsis "Biosequence analysis using profile hidden Markov models")
     (description
@@ -1773,6 +1822,8 @@ HMMs).")
     ;; Numpy needs to be propagated when htseq is used as a Python library.
     (propagated-inputs
      `(("python-numpy" ,python2-numpy)))
+    (inputs
+     `(("python-pysam" ,python2-pysam)))
     (native-inputs
      `(("python-setuptools" ,python2-setuptools)))
     (home-page "http://www-huber.embl.de/users/anders/HTSeq/")
@@ -1964,15 +2015,13 @@ command, or queried for specific k-mers with @code{jellyfish query}.")
 (define-public macs
   (package
     (name "macs")
-    (version "2.1.0.20140616")
+    (version "2.1.0.20151222")
     (source (origin
               (method url-fetch)
-              (uri (string-append
-                    "https://pypi.python.org/packages/source/M/MACS2/MACS2-"
-                    version ".tar.gz"))
+              (uri (pypi-uri "MACS2" version))
               (sha256
                (base32
-                "11lmiw6avqhwn75sn59g4lfkrr2kk20r3rgfbx9xfqb8rg9mi2n6"))))
+                "1r2hcz6irhcq7lwbafjks98jbn34hv05avgbdjnp6w6mlfjkf8x5"))))
     (build-system python-build-system)
     (arguments
      `(#:python ,python-2 ; only compatible with Python 2.7
@@ -2359,7 +2408,7 @@ generated using the PacBio Iso-Seq protocol.")
 (define-public prodigal
   (package
     (name "prodigal")
-    (version "2.6.2")
+    (version "2.6.3")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -2368,7 +2417,7 @@ generated using the PacBio Iso-Seq protocol.")
               (file-name (string-append name "-" version ".tar.gz"))
               (sha256
                (base32
-                "0m8sb0fg6lmxrlpzna0am6svbnlmd3dckrhgzxxgb3gxr5fyj284"))))
+                "17srxkqd3jc77xk15pfbgg1a9xahqg7337w95mrsia7mpza4l2c9"))))
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f ;no check target
@@ -3311,6 +3360,61 @@ features; exactSNP: a SNP caller that discovers SNPs by testing signals
 against local background noises.")
     (license license:gpl3+)))
 
+(define-public stringtie
+  (package
+    (name "stringtie")
+    (version "1.2.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://ccb.jhu.edu/software/stringtie/dl/"
+                                  "stringtie-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1cqllsc1maq4kh92isi8yadgzbmnf042hlnalpk3y59aph1z3bfz"))
+              (modules '((guix build utils)))
+              (snippet
+               '(begin
+                  (delete-file-recursively "samtools-0.1.18")
+                  #t))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f ;no test suite
+       #:phases
+       (modify-phases %standard-phases
+         ;; no configure script
+         (delete 'configure)
+         (add-before 'build 'use-system-samtools
+           (lambda _
+             (substitute* "Makefile"
+               (("stringtie: \\$\\{BAM\\}/libbam\\.a")
+                "stringtie: "))
+             (substitute* '("gclib/GBam.h"
+                            "gclib/GBam.cpp")
+               (("#include \"(bam|sam|kstring).h\"" _ header)
+                (string-append "#include <samtools/" header ".h>")))
+             #t))
+         (replace 'install
+          (lambda* (#:key outputs #:allow-other-keys)
+            (let ((bin (string-append (assoc-ref outputs "out") "/bin/")))
+              (install-file "stringtie" bin)
+              #t))))))
+    (inputs
+     `(("samtools" ,samtools-0.1)
+       ("zlib" ,zlib)))
+    (home-page "http://ccb.jhu.edu/software/stringtie/")
+    (synopsis "Transcript assembly and quantification for RNA-Seq data")
+    (description
+     "StringTie is a fast and efficient assembler of RNA-Seq sequence
+alignments into potential transcripts.  It uses a novel network flow algorithm
+as well as an optional de novo assembly step to assemble and quantitate
+full-length transcripts representing multiple splice variants for each gene
+locus.  Its input can include not only the alignments of raw reads used by
+other transcript assemblers, but also alignments of longer sequences that have
+been assembled from those reads.  To identify differentially expressed genes
+between experiments, StringTie's output can be processed either by the
+Cuffdiff or Ballgown programs.")
+    (license license:artistic2.0)))
+
 (define-public vcftools
   (package
     (name "vcftools")
@@ -3355,7 +3459,7 @@ data in the form of VCF files.")
 (define-public vsearch
   (package
     (name "vsearch")
-    (version "1.4.1")
+    (version "1.10.0")
     (source
      (origin
        (method url-fetch)
@@ -3365,7 +3469,7 @@ data in the form of VCF files.")
        (file-name (string-append name "-" version ".tar.gz"))
        (sha256
         (base32
-         "0b1359wbzgb2cm04h7dq05v80vik88hnsv298xxd1q1f2q4ydni7"))
+         "1i3bad7gnn2y3a1yfixzshd99xdkjc8w5bxzgifpysc6jiljwvb5"))
        (modules '((guix build utils)))
        (snippet
         '(begin
@@ -3375,14 +3479,24 @@ data in the form of VCF files.")
 -O3 -mtune=native -Wall -Wsign-compare")
               (string-append "AM_CXXFLAGS=-lcityhash"
                              " -O3 -Wall -Wsign-compare"))
-             (("^__top_builddir__bin_vsearch_SOURCES = cityhash/city.h \\\\")
+             (("^__top_builddir__bin_vsearch_SOURCES = city.h \\\\")
               "__top_builddir__bin_vsearch_SOURCES = \\")
-             (("^cityhash/config.h \\\\") "\\")
-             (("^cityhash/city.cc \\\\") "\\"))
+             (("^city.h \\\\") "\\")
+             (("^citycrc.h \\\\") "\\")
+             (("^libcityhash_a.*") "")
+             (("noinst_LIBRARIES = libcpu_sse2.a libcpu_ssse3.a \
+libcityhash.a")
+              "noinst_LIBRARIES = libcpu_sse2.a libcpu_ssse3.a")
+             (("__top_builddir__bin_vsearch_LDADD = libcpu_ssse3.a \
+libcpu_sse2.a libcityhash.a")
+              "__top_builddir__bin_vsearch_LDADD = libcpu_ssse3.a \
+libcpu_sse2.a -lcityhash"))
            (substitute* "src/vsearch.h"
-             (("^\\#include \"cityhash/city.h\"")
-              "#include <city.h>"))
-           (delete-file-recursively "src/cityhash")
+             (("^\\#include \"city.h\"") "#include <city.h>")
+             (("^\\#include \"citycrc.h\"") "#include <citycrc.h>"))
+           (delete-file "src/city.h")
+           (delete-file "src/citycrc.h")
+           (delete-file "src/city.cc")
            #t))))
     (build-system gnu-build-system)
     (arguments
@@ -3725,13 +3839,13 @@ on Bioconductor or which replace R functions.")
 (define-public r-annotationdbi
   (package
     (name "r-annotationdbi")
-    (version "1.32.2")
+    (version "1.32.3")
     (source (origin
               (method url-fetch)
               (uri (bioconductor-uri "AnnotationDbi" version))
               (sha256
                (base32
-                "08ncdjvq0l44kqyiv32kn9wnbw1xgfb6qjfzfbjpqrcfp1jygz9j"))))
+                "1v6x62hgys5827yg2xayjrd9xawbayzm6wy0q4vxh1s6yxc9bklj"))))
     (properties
      `((upstream-name . "AnnotationDbi")))
     (build-system r-build-system)
@@ -4043,6 +4157,25 @@ extracting the desired features in a convenient format.")
 information about the latest version of the Gene Ontologies.")
     (license license:artistic2.0)))
 
+(define-public r-graph
+  (package
+    (name "r-graph")
+    (version "1.48.0")
+    (source (origin
+              (method url-fetch)
+              (uri (bioconductor-uri "graph" version))
+              (sha256
+               (base32
+                "16w75rji3kv24gfv44w66y1a2y75ax26rl470y3ypna0ndc3rrcd"))))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-biocgenerics" ,r-biocgenerics)))
+    (home-page "http://bioconductor.org/packages/graph")
+    (synopsis "Handle graph data structures in R")
+    (description
+     "This package implements some simple graph handling capabilities for R.")
+    (license license:artistic2.0)))
+
 (define-public r-topgo
   (package
     (name "r-topgo")
@@ -4061,6 +4194,7 @@ information about the latest version of the Gene Ontologies.")
        ("r-biobase" ,r-biobase)
        ("r-biocgenerics" ,r-biocgenerics)
        ("r-go-db" ,r-go-db)
+       ("r-graph" ,r-graph)
        ("r-sparsem" ,r-sparsem)))
     (home-page "http://bioconductor.org/packages/topGO")
     (synopsis "Enrichment analysis for gene ontology")
@@ -4191,6 +4325,110 @@ genomic feature data as long as it has minimal information on the locations of
 genomic intervals.  In addition, it can use BAM or BigWig files as input.")
     (license license:artistic2.0)))
 
+(define-public r-org-hs-eg-db
+  (package
+    (name "r-org-hs-eg-db")
+    (version "3.2.3")
+    (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/"
+                                  "org.Hs.eg.db_" version ".tar.gz"))
+              (sha256
+               (base32
+                "0xicgkbh6xkvs74s1piafqac63dyz2ycdyil4pj4ghhxx2sabm6p"))))
+    (properties
+     `((upstream-name . "org.Hs.eg.db")))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-annotationdbi" ,r-annotationdbi)))
+    (home-page "http://www.bioconductor.org/packages/org.Hs.eg.db/")
+    (synopsis "Genome wide annotation for Human")
+    (description
+     "This package provides mappings from Entrez gene identifiers to various
+annotations for the human genome.")
+    (license license:artistic2.0)))
+
+(define-public r-org-ce-eg-db
+  (package
+    (name "r-org-ce-eg-db")
+    (version "3.2.3")
+    (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/"
+                                  "org.Ce.eg.db_" version ".tar.gz"))
+              (sha256
+               (base32
+                "1d0lx00ybq34yqs6mziaa0lrh77xm0ggsmi76g6k95f77gi7m1sw"))))
+    (properties
+     `((upstream-name . "org.Ce.eg.db")))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-annotationdbi" ,r-annotationdbi)))
+    (home-page "http://www.bioconductor.org/packages/org.Ce.eg.db/")
+    (synopsis "Genome wide annotation for Worm")
+    (description
+     "This package provides mappings from Entrez gene identifiers to various
+annotations for the genome of the model worm Caenorhabditis elegans.")
+    (license license:artistic2.0)))
+
+(define-public r-org-dm-eg-db
+  (package
+    (name "r-org-dm-eg-db")
+    (version "3.2.3")
+    (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/"
+                                  "org.Dm.eg.db_" version ".tar.gz"))
+              (sha256
+               (base32
+                "0mib46c7nr00l7mh290n383za9hyl91a1dc6jhjbk884jmxaxyz6"))))
+    (properties
+     `((upstream-name . "org.Dm.eg.db")))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-annotationdbi" ,r-annotationdbi)))
+    (home-page "http://www.bioconductor.org/packages/org.Dm.eg.db/")
+    (synopsis "Genome wide annotation for Fly")
+    (description
+     "This package provides mappings from Entrez gene identifiers to various
+annotations for the genome of the model fruit fly Drosophila melanogaster.")
+    (license license:artistic2.0)))
+
+(define-public r-org-mm-eg-db
+  (package
+    (name "r-org-mm-eg-db")
+    (version "3.2.3")
+    (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/"
+                                  "org.Mm.eg.db_" version ".tar.gz"))
+              (sha256
+               (base32
+                "0wh1pm3npdg7070875kfgiid3bqkz3q7rq6snhk6bxfvph00298y"))))
+    (properties
+     `((upstream-name . "org.Mm.eg.db")))
+    (build-system r-build-system)
+    (propagated-inputs
+     `(("r-annotationdbi" ,r-annotationdbi)))
+    (home-page "http://www.bioconductor.org/packages/org.Mm.eg.db/")
+    (synopsis "Genome wide annotation for Mouse")
+    (description
+     "This package provides mappings from Entrez gene identifiers to various
+annotations for the genome of the model mouse Mus musculus.")
+    (license license:artistic2.0)))
+
 (define-public r-qtl
  (package
   (name "r-qtl")
diff --git a/gnu/packages/bittorrent.scm b/gnu/packages/bittorrent.scm
index 16673edf68..ae67988d71 100644
--- a/gnu/packages/bittorrent.scm
+++ b/gnu/packages/bittorrent.scm
@@ -202,7 +202,7 @@ interface, for the Transmission BitTorrent daemon.")
 (define-public aria2
   (package
     (name "aria2")
-    (version "1.19.3")
+    (version "1.20.0")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://github.com/tatsuhiro-t/aria2/"
@@ -210,7 +210,7 @@ interface, for the Transmission BitTorrent daemon.")
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
-                "1qwr4al6wlh5f558r0mr1hvdnf7d8ss6qwqn2361k99phk1cdg3a"))))
+                "1l4gzz3yr0cl6a9xdy7843c5sb7afyq0i80wi2hasfpfdx5k95mz"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags '("--enable-libaria2")
@@ -225,7 +225,7 @@ interface, for the Transmission BitTorrent daemon.")
                (("CPPUNIT_TEST_SUITE_REGISTRATION\\(LpdMessageReceiverTest\\);" text)
                 (string-append "// " text))))))))
     (native-inputs
-     `(("pkg-config", pkg-config)))
+     `(("pkg-config" ,pkg-config)))
     (inputs
      `(("c-ares" ,c-ares)
        ("cppunit" ,cppunit) ; for the tests
diff --git a/gnu/packages/compression.scm b/gnu/packages/compression.scm
index 4a31bf79e2..938d4b8718 100644
--- a/gnu/packages/compression.scm
+++ b/gnu/packages/compression.scm
@@ -244,7 +244,7 @@ decompression.")
                "1vk6065dv3a47p86vmp8hv3n1ygd9hraz0gq89gvzlx7lmcb6fsp"))))
     (build-system gnu-build-system)
     (inputs
-     `(("bzip2", bzip2)))
+     `(("bzip2" ,bzip2)))
     (arguments
      `(#:tests? #f ; no tests
        #:phases (modify-phases %standard-phases
diff --git a/gnu/packages/cpio.scm b/gnu/packages/cpio.scm
index 925b0eed5b..e8eede6524 100644
--- a/gnu/packages/cpio.scm
+++ b/gnu/packages/cpio.scm
@@ -35,7 +35,8 @@
                                  version ".tar.bz2"))
              (sha256
               (base32
-               "0vi9q475h1rki53100zml75vxsykzyhrn70hidy41s5c2rc8r6bh"))))
+               "0vi9q475h1rki53100zml75vxsykzyhrn70hidy41s5c2rc8r6bh"))
+             (patches (list (search-patch "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/curl.scm b/gnu/packages/curl.scm
index 222910b655..46e0fa0f16 100644
--- a/gnu/packages/curl.scm
+++ b/gnu/packages/curl.scm
@@ -54,7 +54,16 @@
    (inputs `(("gnutls" ,gnutls)
              ("gss" ,gss)
              ("libidn" ,libidn)
-             ("libssh2" ,libssh2)
+
+             ;; XXX libssh2-1.4 is a temporary package for use only by curl,
+             ;; to allow most users of libssh2 to get the security update for
+             ;; CVE-2016-7087 while postponing the large number of rebuilds
+             ;; entailed by updating curl.  Soon, curl should be updated to
+             ;; use the latest libssh2 and libssh2-1.4 should be removed.
+
+             ;; XXX libssh2-1.4 is vulnerable to CVE-2016-0787.
+             ("libssh2" ,libssh2-1.4)
+
              ("openldap" ,openldap)
              ("zlib" ,zlib)))
    (native-inputs
diff --git a/gnu/packages/databases.scm b/gnu/packages/databases.scm
index df7101b34f..79254eafb9 100644
--- a/gnu/packages/databases.scm
+++ b/gnu/packages/databases.scm
@@ -8,6 +8,7 @@
 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
 ;;; Copyright © 2015 Leo Famulari <leo@famulari.name>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Nils Gillmann <niasterisk@grrlz.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -273,14 +274,14 @@ as a drop-in replacement of MySQL.")
 (define-public postgresql
   (package
     (name "postgresql")
-    (version "9.3.8")
+    (version "9.3.11")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://ftp.postgresql.org/pub/source/v"
                                   version "/postgresql-" version ".tar.bz2"))
               (sha256
                (base32
-                "1ymd98szvx12gyjdb9gr2hlkrb5bjx7mcshqq3xzdifzapkkqp5w"))))
+                "08ba951nfiy516flaw352shj1zslxg4ryx3w5k0adls1r682l8ix"))))
     (build-system gnu-build-system)
     (inputs
      `(("readline" ,readline)
@@ -320,7 +321,7 @@ pictures, sounds, or video.")
     (native-inputs `(("emacs" ,emacs-no-x)
                      ("bc" ,bc)
                      ("bash:include" ,bash "include")
-                     ("libuuid", util-linux)))
+                     ("libuuid" ,util-linux)))
 
     ;; TODO: Add more optional inputs.
     (inputs `(("curl" ,curl)
@@ -822,3 +823,30 @@ supports many data structures including strings, hashes, lists, sets, sorted
 sets, bitmaps and hyperloglogs.")
     (home-page "http://redis.io/")
     (license bsd-3)))
+
+(define-public kyotocabinet
+  (package
+    (name "kyotocabinet")
+    (version "1.2.76")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://fallabs.com/kyotocabinet/pkg/"
+                                  name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0g6js20x7vnpq4p8ghbw3mh9wpqksya9vwhzdx6dnlf354zjsal1"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:configure-flags
+       (list
+        (string-append "LDFLAGS=-Wl,-rpath="
+                       (assoc-ref %outputs "out") "/lib"))))
+    (inputs `(("zlib" ,zlib)))
+    (home-page "http://fallabs.com/kyotocabinet/")
+    (synopsis
+     "Kyoto Cabinet is a modern implementation of the DBM database")
+    (description
+     "Kyoto Cabinet is a standalone file-based database that supports Hash
+and B+ Tree data storage models.  It is a fast key-value lightweight
+database and supports many programming languages.  It is a NoSQL database.")
+    (license gpl3+)))
diff --git a/gnu/packages/dav.scm b/gnu/packages/dav.scm
index 25b665f292..4562193114 100644
--- a/gnu/packages/dav.scm
+++ b/gnu/packages/dav.scm
@@ -52,13 +52,13 @@ clients.")
 (define-public vdirsyncer
   (package
     (name "vdirsyncer")
-    (version "0.8.1")
+    (version "0.9.0")
     (source (origin
              (method url-fetch)
              (uri (pypi-uri "vdirsyncer" version))
              (sha256
               (base32
-               "1abflqw6x30xd2dlj58cr5n62x98kc0ia9f9vr8l64k2z1fjlq78"))))
+               "0s9awjr9v60rr80xcpwmdhkf4v1yqnydahjmxwvxmh64565is465"))))
     (build-system python-build-system)
     (arguments
       `(#:phases (modify-phases %standard-phases
diff --git a/gnu/packages/dictionaries.scm b/gnu/packages/dictionaries.scm
index 1ecfc3f674..ac020b27c8 100644
--- a/gnu/packages/dictionaries.scm
+++ b/gnu/packages/dictionaries.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -28,14 +29,14 @@
 (define-public vera
   (package
     (name "vera")
-    (version "1.22")
+    (version "1.23")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://gnu/vera/vera-" version
                                   ".tar.gz"))
               (sha256
                (base32
-                "1anx6ikwlkg7bn3c5a8xxrp33bvhfgxmncvnqbn2fp1hnbhqh5i7"))))
+                "1az0v563jja8xb4896jyr8yv7jd9zacqyfkjd7psb73v7clg1mzz"))))
     (build-system trivial-build-system)
     (arguments
      `(#:builder (begin
diff --git a/gnu/packages/docker.scm b/gnu/packages/docker.scm
index 06b72ee376..0760001da7 100644
--- a/gnu/packages/docker.scm
+++ b/gnu/packages/docker.scm
@@ -90,7 +90,6 @@ client.")
      `(("python-docker-py" ,python-docker-py)
        ("python-dockerpty" ,python-dockerpty)
        ("python-docopt" ,python-docopt)
-       ("python-enum34" ,python-enum34)
        ("python-jsonschema" ,python-jsonschema)
        ("python-pyyaml" ,python-pyyaml)
        ("python-requests" ,python-requests-2.7)
diff --git a/gnu/packages/dvtm.scm b/gnu/packages/dvtm.scm
index 17c720575c..af16aa8f91 100644
--- a/gnu/packages/dvtm.scm
+++ b/gnu/packages/dvtm.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015 Leo Famulari <leo@famulari.name>
+;;; Copyright © 2015, 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -26,13 +26,14 @@
 (define-public dvtm
   (package
    (name "dvtm")
-   (version "0.14")
+   (version "0.15")
    (source (origin
             (method url-fetch)
             (uri (string-append "http://www.brain-dump.org/projects/dvtm/dvtm-"
                                  version ".tar.gz"))
             (sha256
-             (base32 "0ykl8dz7ivjgdzhmhlgidnp2ffh5gxq9lbg276w7iid4z10v76wa"))))
+             (base32
+              "0475w514b7i3gxk6khy8pfj2gx9l7lv2pwacmq92zn1abv01a84g"))))
    (build-system gnu-build-system)
    (arguments
     `(#:make-flags (list "CC=gcc"
diff --git a/gnu/packages/ebook.scm b/gnu/packages/ebook.scm
index a551c1d075..bf7fe70772 100644
--- a/gnu/packages/ebook.scm
+++ b/gnu/packages/ebook.scm
@@ -60,7 +60,7 @@
 (define-public calibre
   (package
     (name "calibre")
-    (version "2.49.0")
+    (version "2.51.0")
     (source
       (origin
         (method url-fetch)
@@ -69,7 +69,7 @@
                             version ".tar.xz"))
         (sha256
           (base32
-           "0jc476pg07c0nwccprhwgjdlvvb2fdzza9xrjqzc0c42c5v7qzxa"))
+           "1rhpcxic4g2zyr5s3xn8dayyb45l9r8zyniaig8j7pl5kmsfjijn"))
         ;; Remove non-free or doubtful code, see
         ;; https://lists.gnu.org/archive/html/guix-devel/2015-02/msg00478.html
         (modules '((guix build utils)))
diff --git a/gnu/packages/emacs.scm b/gnu/packages/emacs.scm
index fc940eb487..7270fc4932 100644
--- a/gnu/packages/emacs.scm
+++ b/gnu/packages/emacs.scm
@@ -4,7 +4,8 @@
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014, 2015, 2016 Alex Kost <alezost@gmail.com>
 ;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>
-;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2016 Nils Gillmann <niasterisk@grrlz.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -349,10 +350,35 @@ when typing parentheses directly or commenting out code line by line.")
 configuration files, such as .gitattributes, .gitignore, and .git/config.")
     (license license:gpl3+)))
 
+(define-public emacs-with-editor
+  (package
+    (name "emacs-with-editor")
+    (version "2.5.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/magit/with-editor/archive/v"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "19gb381z61l2icg5v5pymgi1a11g3zdp5aysl2j5fh7fxxg4d4c0"))))
+    (build-system emacs-build-system)
+    (propagated-inputs
+     `(("emacs-dash" ,emacs-dash)))
+    (home-page "https://github.com/magit/with-editor")
+    (synopsis "Emacs library for using Emacsclient as EDITOR")
+    (description
+     "This package provides an Emacs library to use the Emacsclient as
+@code{$EDITOR} of child processes, making sure they know how to call home.
+For remote processes a substitute is provided, which communicates with Emacs
+on stdout instead of using a socket as the Emacsclient does.")
+    (license license:gpl3+)))
+
 (define-public magit
   (package
     (name "magit")
-    (version "2.4.0")
+    (version "2.5.0")
     (source (origin
              (method url-fetch)
              (uri (string-append
@@ -360,12 +386,14 @@ configuration files, such as .gitattributes, .gitignore, and .git/config.")
                    version "/" name "-" version ".tar.gz"))
              (sha256
               (base32
-               "1wbam4l36061mj79qlgzrv4xbzhk2dk6gnv45610zwfnf24ikdsp"))))
+               "0i6qpx5szzc4kyfcdhaic8gif0sqdqcya1niyj93lpvw66jcxsxa"))))
     (build-system gnu-build-system)
     (native-inputs `(("texinfo" ,texinfo)
                      ("emacs" ,emacs-no-x)))
     (inputs `(("git" ,git)))
-    (propagated-inputs `(("dash" ,emacs-dash)))
+    (propagated-inputs
+     `(("dash" ,emacs-dash)
+       ("with-editor" ,emacs-with-editor)))
     (arguments
      `(#:modules ((guix build gnu-build-system)
                   (guix build utils)
@@ -383,7 +411,11 @@ configuration files, such as .gitattributes, .gitignore, and .git/config.")
              (string-append "DASH_DIR="
                             (assoc-ref %build-inputs "dash")
                             "/share/emacs/site-lisp/guix.d/dash-"
-                            ,(package-version emacs-dash)))
+                            ,(package-version emacs-dash))
+             (string-append "WITH_EDITOR_DIR="
+                            (assoc-ref %build-inputs "with-editor")
+                            "/share/emacs/site-lisp/guix.d/with-editor-"
+                            ,(package-version emacs-with-editor)))
 
        #:phases
        (modify-phases %standard-phases
@@ -890,6 +922,27 @@ like.  It can be linked with various Emacs mail clients (Message and Mail
 mode, Rmail, Gnus, MH-E, and VM).  BBDB is fully customizable.")
     (license license:gpl3+)))
 
+(define-public emacs-async
+  (package
+    (name "emacs-async")
+    (version "1.6")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://elpa.gnu.org/packages/async-"
+                                  version ".tar"))
+              (sha256
+               (base32
+                "17psvz75n42x33my967wkgi7r0blx46n3jdv510j0z5jswv66039"))))
+    (build-system emacs-build-system)
+    (home-page "http://elpa.gnu.org/packages/async.html")
+    (synopsis "Asynchronous processing in Emacs")
+    (description
+     "This package provides the ability to call asynchronous functions and
+processes.  For example, it can be used to run dired commands (for copying,
+moving, etc.) asynchronously using @code{dired-async-mode}.  Also it is used
+as a library for other Emacs packages.")
+    (license license:gpl3+)))
+
 (define-public emacs-auctex
   (package
     (name "emacs-auctex")
@@ -1136,15 +1189,17 @@ source code using IPython.")
 (define-public emacs-debbugs
   (package
     (name "emacs-debbugs")
-    (version "0.7")
+    (version "0.9")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://elpa.gnu.org/packages/debbugs-"
                                   version ".tar"))
               (sha256
                (base32
-                "0pbglx3paa8icazgxlg4jf40wl8war63y9j2jmbb7gbd1xp95v72"))))
+                "1wc6kw7hihqqdx8qyl01akygycnan44x400hwrcf54m3hb4isa0k"))))
     (build-system emacs-build-system)
+    (propagated-inputs
+     `(("emacs-async" ,emacs-async)))
     (home-page "http://elpa.gnu.org/packages/debbugs.html")
     (synopsis "Access the Debbugs bug tracker in Emacs")
     (description
@@ -1398,3 +1453,54 @@ supports editing Lisp source files, @{slime-mode} adds support for
 interacting with a running Common Lisp process for compilation,
 debugging, documentation lookup, and so on.")
     (license license:gpl2+)))
+
+(define-public emacs-popup
+  (package
+    (name "emacs-popup")
+    (version "0.5.3")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/auto-complete/popup-el/archive/v"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "1yrgfj8y69xmcb6kwgplhq68ndm9410qwh7sd2knnd1gchpphdc0"))))
+    (build-system emacs-build-system)
+    (native-inputs
+     `(("emacs" ,emacs-no-x)))
+    (home-page "https://github.com/auto-complete/popup-el")
+    (synopsis "Visual Popup User Interface for Emacs")
+    (description
+     "Popup.el is a visual popup user interface library for Emacs.
+This provides a basic API and common UI widgets such as popup tooltips
+and popup menus.")
+    (license license:gpl3+)))
+
+(define-public emacs-god-mode
+  (let ((commit "6cf0807b6555eb6fcf8387a4e3b667071ef38964")
+        (revision "1"))
+    (package
+      (name "emacs-god-mode")
+      (version (string-append "20151005.925."
+                              revision "-" (string-take commit 9)))
+      (source
+       (origin
+         (method git-fetch)
+         (uri (git-reference
+               (url "https://github.com/chrisdone/god-mode.git")
+               (commit commit)))
+         (file-name (string-append name "-" version "-checkout"))
+         (sha256
+          (base32
+           "1am415k4xxcva6y3vbvyvknzc6bma49pq3p85zmpjsdmsp18qdix"))))
+      (build-system emacs-build-system)
+      (home-page "https://github.com/chrisdone/god-mode")
+      (synopsis "Minor mode for entering commands without modifier keys")
+      (description
+       "This package provides a global minor mode for entering Emacs commands
+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+))))
diff --git a/gnu/packages/engineering.scm b/gnu/packages/engineering.scm
index ba11f528cb..9a36ffbb31 100644
--- a/gnu/packages/engineering.scm
+++ b/gnu/packages/engineering.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -55,47 +56,43 @@
 (define-public librecad
   (package
     (name "librecad")
-    (version "2.0.6-rc")
+    (version "2.0.9")
     (source (origin
               (method url-fetch)
               (uri (string-append
                     "https://github.com/LibreCAD/LibreCAD/archive/"
                     version ".tar.gz"))
-              (file-name (string-append name "-" version))
+              (file-name (string-append name "-" version ".tar.gz"))
               (sha256
                (base32
-                "1n1mh8asj6yrl5hi438dvizmrbqk1kni5xkizhi3pdmkg7z3hksm"))))
+                "0xyn4ps9ia94h0vg53rsww8xfd1bgp4200phl8ihyhv7w5v4d8d0"))))
     (build-system gnu-build-system)
     (arguments
      '(#:phases
-       (alist-cons-after
-        'unpack
-        'patch-paths
-        (lambda* (#:key outputs #:allow-other-keys)
-          (let ((out (assoc-ref outputs "out")))
-            (substitute* "librecad/src/lib/engine/rs_system.cpp"
-              (("/usr/share") (string-append out "/share")))))
-        (alist-replace
-         'configure
+       (modify-phases %standard-phases
+        (add-after 'unpack 'patch-paths
+         (lambda* (#:key outputs #:allow-other-keys)
+           (let ((out (assoc-ref outputs "out")))
+             (substitute* "librecad/src/lib/engine/rs_system.cpp"
+               (("/usr/share") (string-append out "/share"))))))
+        (replace 'configure
          (lambda* (#:key inputs #:allow-other-keys)
            (system* "qmake" (string-append "BOOST_DIR="
-                                           (assoc-ref inputs "boost"))))
-         (alist-replace
-          'install
-          (lambda* (#:key outputs #:allow-other-keys)
-            (let ((out (assoc-ref outputs "out")))
-              (mkdir-p (string-append out "/bin"))
-              (mkdir-p (string-append out "/share/librecad"))
-              (copy-file "unix/librecad"
-                         (string-append out "/bin/librecad"))
-              (copy-recursively "unix/resources"
-                                (string-append out "/share/librecad"))))
-          %standard-phases)))))
+                                           (assoc-ref inputs "boost")))))
+        (replace 'install
+         (lambda* (#:key outputs #:allow-other-keys)
+           (let ((out (assoc-ref outputs "out")))
+             (mkdir-p (string-append out "/bin"))
+             (mkdir-p (string-append out "/share/librecad"))
+             (copy-file "unix/librecad"
+                        (string-append out "/bin/librecad"))
+             (copy-recursively "unix/resources"
+                               (string-append out "/share/librecad"))))))))
     (inputs
      `(("boost" ,boost)
        ("muparser" ,muparser)
        ("freetype" ,freetype)
-       ("qt" ,qt-4)))
+       ("qt" ,qt)))
     (native-inputs
      `(("pkg-config" ,pkg-config)
        ("which" ,which)))
@@ -206,31 +203,12 @@ and design rule checking.  It also includes an autorouter and a trace
 optimizer; and it can produce photorealistic and design review images.")
     (license license:gpl2+)))
 
-(define* (broken-tarball-fetch url hash-algo hash
-                               #:optional name
-                               #:key (system (%current-system))
-                               (guile (default-guile)))
-  (mlet %store-monad ((drv (url-fetch url hash-algo hash
-                                      (string-append "tarbomb-" name)
-                                      #:system system
-                                      #:guile guile)))
-    ;; Take the tar bomb, and simply unpack it as a directory.
-    (gexp->derivation name
-                      #~(begin
-                          (mkdir #$output)
-                          (setenv "PATH"
-                                  (string-append #$gzip "/bin"))
-                          (chdir #$output)
-                          (zero? (system* (string-append #$tar "/bin/tar")
-                                          "xf" #$drv))))))
-
-
 (define-public fastcap
   (package
     (name "fastcap")
     (version "2.0-18Sep92")
     (source (origin
-              (method broken-tarball-fetch)
+              (method url-fetch/tarbomb)
               (file-name (string-append name "-" version ".tar.gz"))
               (uri (string-append "http://www.rle.mit.edu/cpg/codes/"
                                   name "-" version ".tgz"))
diff --git a/gnu/packages/feh.scm b/gnu/packages/feh.scm
index ee3fcc6b8b..6b998aa983 100644
--- a/gnu/packages/feh.scm
+++ b/gnu/packages/feh.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 Ian Denhardt <ian@zenhack.net>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -29,7 +30,7 @@
 (define-public feh
   (package
     (name "feh")
-    (version "2.14")
+    (version "2.14.1")
     (home-page "https://feh.finalrewind.org/")
     (source (origin
               (method url-fetch)
@@ -37,7 +38,7 @@
                                   name "-" version ".tar.bz2"))
               (sha256
                (base32
-                "0j5wxpqccnd0hl74z2vwv25n7qnik1n2mcm2jn0c0z7cjn4wsa9q"))))
+                "1hlzgr0masgbm1vdn085vz81s9kpnah8kjkb1w1xfsxr1b99x8f0"))))
     (build-system gnu-build-system)
     (arguments
       '(#:phases (alist-delete 'configure %standard-phases)
diff --git a/gnu/packages/finance.scm b/gnu/packages/finance.scm
index 264cfbf7f3..e9487d4207 100644
--- a/gnu/packages/finance.scm
+++ b/gnu/packages/finance.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -35,7 +36,7 @@
 (define-public bitcoin-core
   (package
     (name "bitcoin-core")
-    (version "0.11.0")
+    (version "0.11.2")
     (source (origin
              (method url-fetch)
              (uri
@@ -44,11 +45,11 @@
                              version ".tar.gz"))
              (sha256
               (base32
-               "17yh6lq13xzzi5v2i48qaxiqm40x3hrj4gwyamkib9yzmmb1gfji"))))
+               "1lwh0vhw1gf3h6zrhynvad9y9qbpmhc8cw1zvj11yzsz5rjbvlm4"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
-       ("python" ,python-wrapper) ; for the tests
+       ("python" ,python-2) ; for the tests
        ("util-linux" ,util-linux))) ; provides the hexdump command for tests
     (inputs
      `(("bdb" ,bdb)
diff --git a/gnu/packages/fonts.scm b/gnu/packages/fonts.scm
index cfdcac8f7f..69e195dbf0 100644
--- a/gnu/packages/fonts.scm
+++ b/gnu/packages/fonts.scm
@@ -6,6 +6,7 @@
 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
 ;;; Copyright © 2015 Eric Dvorsak <eric@dvorsak.fr>
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2016 Nils Gillmann <niasterisk@grrlz.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -354,7 +355,7 @@ The Liberation Fonts are sponsored by Red Hat.")
 (define-public font-terminus
   (package
     (name "font-terminus")
-    (version "4.39")
+    (version "4.40")
     (source
       (origin
         (method url-fetch)
@@ -365,14 +366,14 @@ The Liberation Fonts are sponsored by Red Hat.")
                version
                ".tar.gz"))
         (sha256
-          (base32
-            "1gzmn7zakvy6yrvmswyjfklnsvqrjm0imhq8rjws8rdkhqwkh21i"))))
+         (base32
+          "0487cyx5h1f0crbny5sg73a22gmym5vk1i7646gy7hgiscj2rxb4"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
        ("perl" ,perl)
        ("bdftopcf" ,bdftopcf)
-       ("font-util", font-util)
+       ("font-util" ,font-util)
        ("mkfontdir" ,mkfontdir)))
     (arguments
      `(#:configure-flags (list
diff --git a/gnu/packages/fontutils.scm b/gnu/packages/fontutils.scm
index f31b905156..b8d931fc82 100644
--- a/gnu/packages/fontutils.scm
+++ b/gnu/packages/fontutils.scm
@@ -1,6 +1,7 @@
 ;;; 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 © 2016 Mark H Weaver <mhw@netris.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -75,7 +76,7 @@ anti-aliased glyph bitmap generation with 256 gray levels.")
    (source (origin
             (method url-fetch)
             (uri (string-append
-                   "http://www.freedesktop.org/software/fontconfig/release/fontconfig-"
+                   "https://www.freedesktop.org/software/fontconfig/release/fontconfig-"
                    version ".tar.bz2"))
             (sha256 (base32
                      "1psrl4b4gi4wmbvwwh43lk491wsl8lgvqj146prlcha3vwjc0qyp"))))
@@ -203,16 +204,16 @@ applications should be.")
 (define-public graphite2
   (package
    (name "graphite2")
-   (version "1.3.3")
+   (version "1.3.5")
    (source
      (origin
        (method url-fetch)
-       (uri (string-append
-              "mirror://sourceforge/silgraphite/graphite2/graphite2-"
-              version ".tgz"))
+       (uri (string-append "https://github.com/silnrsi/graphite/archive/"
+                           version ".tar.gz"))
+       (file-name (string-append name "-" version ".tar.gz"))
        (sha256
          (base32
-           "1n22vvi4jl83m4sqhvd7v31bhyhyd8j6c3yjgh4zjfyrvid16jrg"))))
+           "0jrjb56zim57xg2pckfdyrw46c624mqz9zywgwza0g1bxg26940w"))))
    (build-system cmake-build-system)
    (native-inputs
     `(("python" ,python-2) ; because of "import imap" in tests
@@ -226,7 +227,7 @@ engine.  Graphite is a smart font technology designed to facilitate the
 process known as shaping.  This process takes an input Unicode text string
 and returns a sequence of positioned glyphids from the font.")
    (license license:lgpl2.1+)
-   (home-page "http://projects.palaso.org/projects/graphitedev")))
+   (home-page "https://github.com/silnrsi/graphite")))
 
 (define-public potrace
   (package
@@ -258,6 +259,28 @@ resolution.")
     (license license:gpl2+)
     (home-page "http://potrace.sourceforge.net/")))
 
+(define-public libotf
+  (package
+    (name "libotf")
+    (version "0.9.13")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "mirror://savannah/releases/m17n/libotf-"
+                    version ".tar.gz"))
+              (sha256
+               (base32 "0239zvfan56w7vrppriwy77fzb10ag9llaz15nsraps2a2x6di3v"))))
+    (build-system gnu-build-system)
+    (propagated-inputs
+     `(("freetype" ,freetype)))
+    (home-page "http://www.nongnu.org/m17n/")
+    (synopsis "Library for handling OpenType Font")
+    (description "This library can read Open Type Layout Tables from an OTF
+file.  Currently these tables are supported; head, name, cmap, GDEF, GSUB, and
+GPOS.  It can convert a Unicode character sequence to a glyph code sequence by
+using the above tables.")
+    (license license:lgpl2.0+)))
+
 (define-public libspiro
   (package
     (name "libspiro")
diff --git a/gnu/packages/freedesktop.scm b/gnu/packages/freedesktop.scm
index e87b4a3b0d..bfe6e4569c 100644
--- a/gnu/packages/freedesktop.scm
+++ b/gnu/packages/freedesktop.scm
@@ -61,12 +61,15 @@
       (origin
         (method url-fetch)
           (uri (string-append
-                 "http://portland.freedesktop.org/download/xdg-utils-"
+                 "https://portland.freedesktop.org/download/xdg-utils-"
                  version ".tgz"))
           (sha256
             (base32
              "1b019d3r1379b60p33d6z44kx589xjgga62ijz9vha95dg8vgbi1"))))
     (build-system gnu-build-system)
+    (propagated-inputs
+     `(("xprop" ,xprop) ; for Xfce detecting
+       ("xset" ,xset))) ; for xdg-screensaver
     (arguments
      `(#:tests? #f)) ; no check target
     (home-page "http://portland.freedesktop.org/")
@@ -79,14 +82,14 @@ freedesktop.org project.")
 (define-public libinput
   (package
     (name "libinput")
-    (version "0.21.0")
+    (version "1.1.902")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://freedesktop.org/software/libinput/"
+              (uri (string-append "https://freedesktop.org/software/libinput/"
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
-                "0l7mhdr50g11hxg2pz8ihsgzbm0810syj05d3555rzhda6g7mkkw"))))
+                "19wa5yizc3nfq3gibyqb3ygdvcs7v7bz1m5ifv0f4va3igxc3nk3"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
@@ -94,7 +97,8 @@ freedesktop.org project.")
      `(("libudev" ,eudev))) ; required by libinput.pc
     (inputs
      `(("libevdev" ,libevdev)
-       ("mtdev" ,mtdev)))
+       ("mtdev" ,mtdev)
+       ("libwacom" ,libwacom)))
     (home-page "http://www.freedesktop.org/wiki/Software/libinput/")
     (synopsis "Input devices handling library")
     (description
@@ -174,7 +178,7 @@ the freedesktop.org XDG Base Directory specification.")
        ("xsltproc" ,libxslt)
        ("m4" ,m4)
        ("libxml2" ,libxml2)                     ;for XML_CATALOG_FILES
-       ("pkg-config", pkg-config)
+       ("pkg-config" ,pkg-config)
        ("gperf" ,gperf)))
     (inputs
      `(("linux-pam" ,linux-pam)
@@ -246,7 +250,7 @@ Python.")
     (version "1.9.0")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://wayland.freedesktop.org/releases/"
+              (uri (string-append "https://wayland.freedesktop.org/releases/"
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
@@ -281,7 +285,7 @@ applications, X servers (rootless or fullscreen) or other display servers.")
     (source (origin
              (method url-fetch)
              (uri (string-append
-                   "http://libopenraw.freedesktop.org/download/"
+                   "https://libopenraw.freedesktop.org/download/"
                    name "-" version ".tar.bz2"))
              (sha256
               (base32
@@ -330,7 +334,7 @@ Analysis and Reporting Technology) functionality.")
     (version "2.1.6")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://udisks.freedesktop.org/releases/"
+              (uri (string-append "https://udisks.freedesktop.org/releases/"
                                   name "-" version ".tar.bz2"))
               (sha256
                (base32
@@ -500,7 +504,7 @@ which speak the Qualcomm MSM Interface (QMI) protocol.")
     (source (origin
               (method url-fetch)
               (uri (string-append
-                    "http://www.freedesktop.org/software/ModemManager/"
+                    "https://www.freedesktop.org/software/ModemManager/"
                     "ModemManager-" version ".tar.xz"))
               (sha256
                (base32
@@ -540,14 +544,15 @@ modems and setup connections with them.")
     (version "0.8.2")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://telepathy.freedesktop.org/releases/"
+              (uri (string-append "https://telepathy.freedesktop.org/releases/"
                                   name "/" name "-" version ".tar.bz2"))
               (sha256
                (base32
                 "1bjx85k7jyfi5pvl765fzc7q2iz9va51anrc2djv7caksqsdbjlg"))))
     (build-system gnu-build-system)
     (arguments
-     '(#:phases
+     '(#:parallel-tests? #f
+       #:phases
        (modify-phases %standard-phases
          (add-before 'check 'pre-check
           (lambda _
@@ -579,7 +584,7 @@ different sorts of messages in different formats.")
     (version "0.1.26")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://www.freedesktop.org/software/colord"
+              (uri (string-append "https://www.freedesktop.org/software/colord"
                                   "/releases/" name "-" version ".tar.xz"))
               (sha256
                (base32
diff --git a/gnu/packages/fribidi.scm b/gnu/packages/fribidi.scm
index eb13aa1c6d..735fdab8e8 100644
--- a/gnu/packages/fribidi.scm
+++ b/gnu/packages/fribidi.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.
 ;;;
@@ -25,7 +26,7 @@
 (define-public fribidi
   (package
     (name "fribidi")
-    (version "0.19.6")
+    (version "0.19.7")
     (source
       (origin
         (method url-fetch)
@@ -33,7 +34,7 @@
           (string-append "http://fribidi.org/download/" name "-" version
                          ".tar.bz2"))
         (sha256
-          (base32 "0zg1hpaml34ny74fif97j7ngrshlkl3wk3nja3gmlzl17i1bga6b"))))
+          (base32 "13jsb5qadlhsaxkbrb49nqslmbh904vvzhsm5mm2ghmv29i2l8h8"))))
 
     (build-system gnu-build-system)
     (synopsis "Implementation of the Unicode bidirectional algorithm")
diff --git a/gnu/packages/games.scm b/gnu/packages/games.scm
index 7eb0e7a630..991fa24697 100644
--- a/gnu/packages/games.scm
+++ b/gnu/packages/games.scm
@@ -14,6 +14,7 @@
 ;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
 ;;; Copyright © 2015 Paul van der Walt <paul@denknerd.org>
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
+;;; Copyright © 2016 Rodger Fox <thylakoid@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -44,6 +45,7 @@
   #:use-module (gnu packages base)
   #:use-module (gnu packages admin)
   #:use-module (gnu packages audio)
+  #:use-module (gnu packages avahi)
   #:use-module (gnu packages boost)
   #:use-module (gnu packages fribidi)
   #:use-module (gnu packages game-development)
@@ -845,7 +847,7 @@ either by Infocom or created using the Inform compiler.")
 (define-public retroarch
   (package
     (name "retroarch")
-    (version "1.2.2")
+    (version "1.3.1")
     (source
      (origin
        (method url-fetch)
@@ -853,7 +855,7 @@ either by Infocom or created using the Inform compiler.")
                            version ".tar.gz"))
        (file-name (string-append name "-" version ".tar.gz"))
        (sha256
-        (base32 "1bxr8yhk3ad4df544qljsfjfhxa8zy1grq7rn1s02yfvdmgzf4qi"))))
+        (base32 "1wydzvligyby05x8c4lpg6xcnw9qkmvkskyhzc28xq10vm3q57fv"))))
     (build-system gnu-build-system)
     (arguments
      '(#:tests? #f ; no tests
@@ -995,7 +997,7 @@ This game is based on the GPL version of the famous game TuxRacer.")
           (lambda _ (setenv "LIBS" "-lm"))))))
     (inputs
      `(("glu" ,glu)
-       ("mesa", mesa)
+       ("mesa" ,mesa)
        ("sdl" ,sdl)
        ("sdl-image" ,sdl-image)
        ("sdl-mixer" ,sdl-mixer)))
@@ -1891,3 +1893,27 @@ and a game metadata scraper.")
     (description "The Emilia Pinball Project is a pinball simulator.  There
 are only two levels to play with, but they are very addictive.")
     (license license:gpl2)))
+
+(define-public pioneers
+  (package
+    (name "pioneers")
+    (version "15.3")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://downloads.sourceforge.net/pio/"
+                                  "pioneers-" version ".tar.gz"))
+              (sha256
+               (base32
+                "128s718nnraiznbg2rajjqb7cfkdg24hy6spdd9narb4f4dsbbv9"))))
+    (build-system gnu-build-system)
+    (inputs `(("gtk+" ,gtk+)
+              ("librsvg" ,librsvg)
+              ("avahi" ,avahi)))
+    (native-inputs `(("intltool" ,intltool)
+                     ("pkg-config" ,pkg-config)))
+    (synopsis "Board game inspired by The Settlers of Catan")
+    (description "Pioneers is an emulation of the board game The Settlers of
+Catan.  It can be played on a local network, on the internet, and with AI
+players.")
+    (home-page "http://pio.sourceforge.net/")
+    (license license:gpl2+)))
diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm
index 832e57bc77..e15b07752b 100644
--- a/gnu/packages/gcc.scm
+++ b/gnu/packages/gcc.scm
@@ -470,8 +470,8 @@ as the 'native-search-paths' field."
   (custom-gcc gcc-5 "gfortran" '("fortran")
               %generic-search-paths))
 
-(define-public gccgo-4.8
-  (custom-gcc gcc-4.8 "gccgo" '("go")
+(define-public gccgo-4.9
+  (custom-gcc gcc-4.9 "gccgo" '("go")
               %generic-search-paths
               ;; Suppress the separate "lib" output, because otherwise the
               ;; "lib" and "out" outputs would refer to each other, creating
diff --git a/gnu/packages/gdb.scm b/gnu/packages/gdb.scm
index 81d6a8950d..9065732c78 100644
--- a/gnu/packages/gdb.scm
+++ b/gnu/packages/gdb.scm
@@ -1,7 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -37,14 +37,14 @@
 (define-public gdb
   (package
     (name "gdb")
-    (version "7.10.1")
+    (version "7.11")
     (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnu/gdb/gdb-"
                                  version ".tar.xz"))
              (sha256
               (base32
-               "1mfnjcwnwm5cg4rc9pncs9v356a0bz6ymjyac56mbj6784yjzir5"))))
+               "1hg5kwwdvi9b9nxzxfjnx8fx3gip75fqyvkp82xpf3b3rcb42hvs"))))
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f ; FIXME "make check" fails on single-processor systems.
diff --git a/gnu/packages/ghostscript.scm b/gnu/packages/ghostscript.scm
index 818072ac5e..d2eb066817 100644
--- a/gnu/packages/ghostscript.scm
+++ b/gnu/packages/ghostscript.scm
@@ -282,7 +282,7 @@ Ghostscript.  It currently includes the 35 standard PostScript fonts.")
    (version "0.2.7")
    (source (origin
             (method url-fetch)
-            (uri (string-append "http://libspectre.freedesktop.org/releases/libspectre-"
+            (uri (string-append "https://libspectre.freedesktop.org/releases/libspectre-"
                                 version ".tar.gz"))
             (sha256 (base32
                      "1v63lqc6bhhxwkpa43qmz8phqs8ci4dhzizyy16d3vkb20m846z8"))))
diff --git a/gnu/packages/gl.scm b/gnu/packages/gl.scm
index 33312ba127..907e3bf30a 100644
--- a/gnu/packages/gl.scm
+++ b/gnu/packages/gl.scm
@@ -192,7 +192,7 @@ also known as DXTn or DXTC) for Mesa.")
 (define-public mesa
   (package
     (name "mesa")
-    (version "11.0.3")
+    (version "11.0.9")
     (source
       (origin
         (method url-fetch)
@@ -200,7 +200,7 @@ also known as DXTn or DXTC) for Mesa.")
                             version "/mesa-" version ".tar.xz"))
         (sha256
          (base32
-          "1mikw0biw0wxq0fn3cp18bm6kjrkd66fy84774yc5b91rvp94adb"))))
+          "009b3nq8ly5nzy9cxi9cxf4qasrhggjz0v0q87rwq5kaqvqjy9m1"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("glproto" ,glproto)
diff --git a/gnu/packages/glib.scm b/gnu/packages/glib.scm
index f8e1541f56..b925704aa0 100644
--- a/gnu/packages/glib.scm
+++ b/gnu/packages/glib.scm
@@ -384,7 +384,7 @@ translated.")
     (source (origin
              (method url-fetch)
              (uri
-              (string-append "http://dbus.freedesktop.org/releases/dbus-glib/dbus-glib-"
+              (string-append "https://dbus.freedesktop.org/releases/dbus-glib/dbus-glib-"
                              version ".tar.gz"))
              (sha256
               (base32
@@ -574,7 +574,7 @@ useful for C++.")
       (method url-fetch)
        (uri
         (string-append
-         "http://telepathy.freedesktop.org/releases/telepathy-glib/"
+         "https://telepathy.freedesktop.org/releases/telepathy-glib/"
          "telepathy-glib-" version ".tar.gz"))
        (sha256
         (base32
diff --git a/gnu/packages/gnome.scm b/gnu/packages/gnome.scm
index 49e61973a0..0960b534f1 100644
--- a/gnu/packages/gnome.scm
+++ b/gnu/packages/gnome.scm
@@ -13,6 +13,7 @@
 ;;; Copyright © 2015 David Thompson <davet@gnu.org>
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 Rene Saavedra <rennes@openmailbox.org>
+;;; Copyright © 2016 Jochem Raat <jchmrt@riseup.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -36,6 +37,7 @@
   #:use-module (guix utils)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system glib-or-gtk)
+  #:use-module (guix build-system trivial)
   #:use-module (gnu packages)
   #:use-module (gnu packages admin)
   #:use-module (gnu packages autotools)
@@ -500,7 +502,7 @@ for settings shared by various components of the GNOME desktop.")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "http://tango.freedesktop.org/releases/icon-naming-utils-"
+      (uri (string-append "https://tango.freedesktop.org/releases/icon-naming-utils-"
                           version ".tar.bz2"))
       (sha256
        (base32
@@ -536,7 +538,7 @@ GNOME and KDE desktops to the icon names proposed in the specification.")
     (version "0.22")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://www.freedesktop.org/software/" name
+              (uri (string-append "https://www.freedesktop.org/software/" name
                                   "/releases/" name "-" version ".tar.xz"))
               (sha256
                (base32
@@ -608,7 +610,7 @@ update-desktop-database: updates the database containing a cache of MIME types
     (version "1.2")
     (source (origin
              (method url-fetch)
-             (uri (string-append "http://freedesktop.org/~hadess/"
+             (uri (string-append "https://freedesktop.org/~hadess/"
                                  "shared-mime-info-" version ".tar.xz"))
              (sha256
               (base32
@@ -640,7 +642,7 @@ database is translated at Transifex.")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "http://icon-theme.freedesktop.org/releases/"
+      (uri (string-append "https://icon-theme.freedesktop.org/releases/"
                           "hicolor-icon-theme-" version ".tar.gz"))
       (sha256
        (base32
@@ -939,7 +941,7 @@ library.")
     (inputs `(("glib" ,glib)))
     (native-inputs
      `(("pkg-config" ,pkg-config)
-       ("flex", flex)
+       ("flex" ,flex)
        ("bison" ,bison)))
     (home-page "http://freecode.com/projects/libidl")
     (synopsis "Create trees of CORBA Interface Definition Language files")
@@ -1583,7 +1585,7 @@ Hints specification (EWMH).")
        ("libxml2" ,libxml2)
        ("libxslt" ,libxslt)
        ("python" ,python-2)
-       ("python2-pygobject", python2-pygobject-2)
+       ("python2-pygobject" ,python2-pygobject-2)
        ("zlib" ,zlib)))
     (native-inputs
      `(("intltool" ,intltool)
@@ -2259,7 +2261,7 @@ keyboard shortcuts.")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "http://www.freedesktop.org/software/colord/releases/"
+       (uri (string-append "https://www.freedesktop.org/software/colord/releases/"
                            name "-" version ".tar.xz"))
        (sha256
         (base32
@@ -2323,7 +2325,7 @@ output devices.")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "http://www.freedesktop.org/software/" name
+       (uri (string-append "https://www.freedesktop.org/software/" name
                            "/releases/" (version-major+minor version) "/"
                            name "-" version ".tar.xz"))
        (sha256
@@ -2403,7 +2405,7 @@ faster results and to avoid unnecessary server load.")
     (version "0.99.3")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://upower.freedesktop.org/releases/"
+              (uri (string-append "https://upower.freedesktop.org/releases/"
                                   name "-" version ".tar.xz"))
               (sha256
                (base32
@@ -3228,7 +3230,7 @@ supports playlists, song ratings, and any codecs installed through gstreamer.")
     `(("dconf" ,dconf)))
    (native-inputs
     `(("intltool" ,intltool)
-      ("itstool", itstool)
+      ("itstool" ,itstool)
       ("glib" ,glib "bin")
       ("gobject-introspection" ,gobject-introspection)
       ("pkg-config" ,pkg-config)
@@ -3879,7 +3881,7 @@ javascript engine and the GObject introspection framework.")
      `(("dconf" ,dconf)))
     (native-inputs
      `(("intltool" ,intltool)
-       ("itstool", itstool)
+       ("itstool" ,itstool)
        ("gobject-introspection" ,gobject-introspection)
        ("pkg-config" ,pkg-config)))
     (inputs
@@ -4648,3 +4650,164 @@ as SASL, TLS and VeNCrypt.  Additionally it supports encoding extensions.")
 design and behaviour, giving the user a simple way to navigate and manage its
 files.")
     (license license:gpl2+)))
+
+(define-public baobab
+  (package
+    (name "baobab")
+    (version "3.18.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "mirror://gnome/sources/" name "/"
+                    (version-major+minor version) "/"
+                    name "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "1da4bdkw5bnxansl1xr4lb03d6f4h0a0qaba8i3p3rwhcd191b62"))))
+    (build-system glib-or-gtk-build-system)
+    (native-inputs
+     `(("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)
+       ("itstool" ,itstool)
+       ("xmllint" ,libxml2)
+       ("glib" ,glib "bin")
+       ("vala" ,vala)))
+    (inputs
+     `(("gtk+" ,gtk+)))
+    (synopsis "Disk usage analyzer for GNOME")
+    (description
+     "Baobab (Disk Usage Analyzer) is a graphical application to analyse disk
+usage in the GNOME desktop environment.  It can easily scan device volumes or
+a specific user-requested directory branch (local or remote).  Once the scan
+is complete it provides a graphical representation of each selected folder.")
+    (home-page "https://wiki.gnome.org/Apps/Baobab")
+    (license license:gpl2+)))
+
+(define-public gnome-backgrounds
+  (package
+    (name "gnome-backgrounds")
+    (version "3.18.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "mirror://gnome/sources/" name "/"
+                           (version-major+minor version) "/"
+                           name "-" version ".tar.xz"))
+       (sha256
+        (base32
+         "1fd7y8dh3iy88ayb8irgsihvssli6bzjzb5a6vfhi8qjbw70ymma"))))
+    (build-system glib-or-gtk-build-system)
+    (native-inputs
+     `(("intltool" ,intltool)))
+    (home-page "https://git.gnome.org/browse/gnome-backgrounds")
+    (synopsis "Background images for the GNOME desktop")
+    (description
+     "GNOME backgrounds package contains a collection of graphics files which
+can be used as backgrounds in the GNOME Desktop environment.  Additionally,
+the package creates the proper framework and directory structure so that you
+can add your own files to the collection.")
+    (license (list license:gpl2+
+                   license:cc-by2.0
+                   license:cc-by-sa2.0
+                   license:cc-by-sa3.0))))
+
+(define-public gnome-screenshot
+  (package
+    (name "gnome-screenshot")
+    (version "3.18.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "mirror://gnome/sources/" name "/"
+                           (version-major+minor version) "/"
+                           name "-" version ".tar.xz"))
+       (sha256
+        (base32
+         "0hc8m435q7yzvrw7jpi53kaxpmrd9w59sm7c5wibh2ng9azlv9pb"))))
+    (build-system glib-or-gtk-build-system)
+    (native-inputs
+     `(("glib:bin" ,glib "bin") ; for glib-compile-schemas, etc.
+       ("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)))
+    (inputs
+     `(("gtk+" ,gtk+)
+       ("libcanberra" ,libcanberra)
+       ("libx11" ,libx11)
+       ("libxext" ,libxext)))
+    (home-page "https://git.gnome.org/browse/gnome-screenshot")
+    (synopsis "Take pictures of your screen")
+    (description
+     "GNOME Screenshot is a utility used for taking screenshots of the entire
+screen, a window or a user defined area of the screen, with optional
+beautifying border effects.")
+    (license license:gpl2+)))
+
+(define-public dconf-editor
+  (package
+    (name "dconf-editor")
+    (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
+         "0xdwi7g1xdmgrc9m8ii62fp2zj114gsfpmgazlnhrcmmfi97z5d7"))))
+    (build-system glib-or-gtk-build-system)
+    (native-inputs
+     `(("glib:bin" ,glib "bin") ; for glib-compile-schemas, gio-2.0.
+       ("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)))
+    (inputs
+     `(("dconf" ,dconf)
+       ("gtk+" ,gtk+)
+       ("libxml2" ,libxml2)))
+    (home-page "https://git.gnome.org/browse/dconf-editor")
+    (synopsis "Graphical editor for GNOME's dconf configuration system")
+    (description
+     "Dconf-editor is a graphical tool for browsing and editing the dconf
+configuration system for GNOME.  It allows users to configure desktop
+software that do not provide their own configuration interface.")
+    (license license:lgpl2.1+)))
+
+(define-public gnome
+  (package
+    (name "gnome")
+    (version (package-version gnome-shell))
+    (source #f)
+    (build-system trivial-build-system)
+    (arguments '(#:builder (mkdir %output)))
+    (propagated-inputs
+     ;; TODO: Add more packages according to:
+     ;;       <https://packages.debian.org/jessie/gnome-core>.
+     `(("adwaita-icon-theme"        ,adwaita-icon-theme)
+       ("at-spi2-core"              ,at-spi2-core)
+       ("dbus"                      ,dbus)
+       ("dconf"                     ,dconf)
+       ("eog"                       ,eog)
+       ("epiphany"                  ,epiphany)
+       ("evince"                    ,evince)
+       ("gedit"                     ,gedit)
+       ("glib-networking"           ,glib-networking)
+       ("gnome-control-center"      ,gnome-control-center)
+       ("gnome-keyring"             ,gnome-keyring)
+       ("gnome-session"             ,gnome-session)
+       ("gnome-settings-daemon"     ,gnome-settings-daemon)
+       ("gnome-shell"               ,gnome-shell)
+       ("gnome-terminal"            ,gnome-terminal)
+       ("gnome-themes-standard"     ,gnome-themes-standard)
+       ("hicolor-icon-theme"        ,hicolor-icon-theme)
+       ("nautilus"                  ,nautilus)
+       ("pulseaudio"                ,pulseaudio)
+       ("shared-mime-info"          ,shared-mime-info)
+       ("totem"                     ,totem)
+       ("yelp"                      ,yelp)
+       ("zenity"                    ,zenity)))
+    (synopsis "Desktop environment (meta-package)")
+    (home-page "https://www.gnome.org/")
+    (description
+     "GNOME is an intutive and attractive desktop environment.  It aims to be
+an easy and elegant way to use your computer.")
+    (license license:gpl2+)))
diff --git a/gnu/packages/gnunet.scm b/gnu/packages/gnunet.scm
index 11e5aa8733..eb0c4cbe83 100644
--- a/gnu/packages/gnunet.scm
+++ b/gnu/packages/gnunet.scm
@@ -3,6 +3,8 @@
 ;;; Copyright © 2014 Sree Harsha Totakura <sreeharsha@totakura.in>
 ;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Ni* Gillmann <ng@niasterisk.space>
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,14 +24,17 @@
 (define-module (gnu packages gnunet)
   #:use-module (gnu packages)
   #:use-module (gnu packages file)
+  #:use-module (gnu packages aidc)
   #:use-module (gnu packages autotools)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages curl)
   #:use-module (gnu packages geeqie)
   #:use-module (gnu packages gettext)
   #:use-module (gnu packages glib)
+  #:use-module (gnu packages gnome)
   #:use-module (gnu packages gnupg)
   #:use-module (gnu packages groff)
+  #:use-module (gnu packages gtk)
   #:use-module (gnu packages guile)
   #:use-module (gnu packages gstreamer)
   #:use-module (gnu packages libidn)
@@ -208,6 +213,8 @@ supports HTTPS, HTTPS and GnuTLS.")
    (inputs
     `(("glpk" ,glpk)
       ("gnurl" ,gnurl)
+      ("gstreamer" ,gstreamer)
+      ("gst-plugins-base" ,gst-plugins-base)
       ("gnutls" ,gnutls)
       ("libextractor" ,libextractor)
       ("libgcrypt" ,libgcrypt)
@@ -217,14 +224,16 @@ supports HTTPS, HTTPS and GnuTLS.")
       ("libunistring" ,libunistring)
       ("openssl" ,openssl)
       ("opus" ,opus)
-      ("pulseaudio", pulseaudio)
+      ("pulseaudio" ,pulseaudio)
       ("sqlite" ,sqlite)
       ("zlib" ,zlib)))
    (native-inputs
     `(("pkg-config" ,pkg-config)
       ("python" ,python-2)))
    (arguments
-    '(#:parallel-tests? #f
+    '(#:configure-flags
+      (list (string-append "--with-nssdir=" %output "/lib"))
+      #:parallel-tests? #f
       ;; test_gnunet_service_arm fails; reported upstream
       #:tests? #f
       #:phases
@@ -286,3 +295,33 @@ GNUnet services, including the @dfn{identity} and @dfn{file sharing}
 services.")
       (home-page "http://gnu.org/software/guix")
       (license license:gpl3+))))
+
+;; FIXME: "gnunet-setup" segfaults under certain conditions and "gnunet-gtk"
+;; does not seem to be fully functional.  This has been reported upstream:
+;; http://lists.gnu.org/archive/html/gnunet-developers/2016-02/msg00004.html
+(define-public gnunet-gtk
+  (package (inherit gnunet)
+    (name "gnunet-gtk")
+    (version (package-version gnunet))
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://gnu/gnunet/gnunet-gtk-"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "1p38k1s6a2fmcfc9a7cf1zrdycm9h06kqdyand4s3k500nj6mb4g"))))
+    (arguments
+     `(#:configure-flags
+       (list "--without-libunique"
+             "--with-qrencode")))
+    (inputs
+     `(("gnunet" ,gnunet)
+       ("libgcrypt" ,libgcrypt)
+       ("gtk+" ,gtk+)
+       ("libextractor" ,libextractor)
+       ("glade3" ,glade3)
+       ("qrencode" ,qrencode)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("libglade" ,libglade)))
+    (synopsis "Graphical front-end tools for GNUnet")))
diff --git a/gnu/packages/gnupg.scm b/gnu/packages/gnupg.scm
index a35e8fc401..350865addb 100644
--- a/gnu/packages/gnupg.scm
+++ b/gnu/packages/gnupg.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2012, 2013, 2014, 2015 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 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Paul van der Walt <paul@denknerd.org>
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
@@ -70,14 +70,14 @@ Daemon and possibly more in the future.")
 (define-public libgcrypt
   (package
     (name "libgcrypt")
-    (version "1.6.4")
+    (version "1.6.5")
     (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnupg/libgcrypt/libgcrypt-"
                                  version ".tar.bz2"))
              (sha256
               (base32
-               "09k06gs27gxfha07sa9rpf4xh6mvphj9sky7n09ymx75w9zjrg69"))))
+               "0959mwfzsxhallxdqlw359xg180ll2skxwyy35qawmfl89cbr7pl"))))
     (build-system gnu-build-system)
     (propagated-inputs
      `(("libgpg-error-host" ,libgpg-error)))
@@ -206,7 +206,10 @@ compatible to GNU Pth.")
                                   ".tar.bz2"))
               (sha256
                (base32
-                "06mn2viiwsyq991arh5i5fhr9jyxq2bi0jkdj7ndfisxihngpc5p"))))
+                "06mn2viiwsyq991arh5i5fhr9jyxq2bi0jkdj7ndfisxihngpc5p"))
+              (patches
+               (list (search-patch
+                      "gnupg-simple-query-ignore-status-messages.patch")))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)))
diff --git a/gnu/packages/gnuzilla.scm b/gnu/packages/gnuzilla.scm
index 2ddad9afe2..dca461f5d4 100644
--- a/gnu/packages/gnuzilla.scm
+++ b/gnu/packages/gnuzilla.scm
@@ -72,7 +72,7 @@
                  (("defined\\(@TEMPLATE_FILE)") "@TEMPLATE_FILE")))))
     (build-system gnu-build-system)
     (native-inputs
-      `(("perl", perl)
+      `(("perl" ,perl)
         ("python" ,python-2)))
     (arguments
       `(#:phases
@@ -154,7 +154,7 @@ in C/C++.")
                "01ria9wk6329hxqsy75p9dkxiqkq4nkz0jjzll7hslih3jbi8dil"))))
     (build-system gnu-build-system)
     (native-inputs
-      `(("perl", perl)))
+      `(("perl" ,perl)))
     (arguments
      `(#:tests? #f ; no check target
        #:configure-flags (list "--enable-64bit"
@@ -289,7 +289,8 @@ standards.")
         "0bd4k5cwr8ynscaxffvj2x3kgky3dmjq0qhpcb931l98bh0103lx"))
       (patches (map search-patch
                     '("icecat-avoid-bundled-includes.patch"
-                      "icecat-re-enable-DHE-cipher-suites.patch")))
+                      "icecat-re-enable-DHE-cipher-suites.patch"
+                      "icecat-update-graphite2.patch")))
       (modules '((guix build utils)))
       (snippet
        '(begin
@@ -318,6 +319,8 @@ standards.")
                       ;; TODO: Use system harfbuzz.  Waiting for:
                       ;; <https://bugzilla.mozilla.org/show_bug.cgi?id=847568>
                       ;;
+                      ;; TODO: Use system graphite2.
+                      ;;
                       "modules/freetype2"
                       "modules/zlib"
                       "modules/libbz2"
diff --git a/gnu/packages/gps.scm b/gnu/packages/gps.scm
index bede89e373..fd045b1f1a 100644
--- a/gnu/packages/gps.scm
+++ b/gnu/packages/gps.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -34,7 +35,7 @@
 (define-public gpsbabel
   (package
     (name "gpsbabel")
-    (version "1.5.0")
+    (version "1.5.2")
     (source (origin
               (method url-fetch)
               ;; XXX: Downloads from gpsbabel.org are hidden behind a POST, so
@@ -44,16 +45,16 @@
                     version ".orig.tar.gz"))
               (sha256
                (base32
-                "1pd01kra9l5ihy1by87qia0mpbpcif7g5yg7r9z2bnw7711jm3yb"))))
+                "0xf7wmy2m29g2lm8lqc74yf8rf7sxfl3cfwbk7dpf0yf42pb0b6w"))))
     (build-system gnu-build-system)
     (arguments
      `(#:configure-flags '("--with-zlib=system")
-       #:phases (alist-cons-before
-                 'configure 'pre-configure
-                 (lambda _
-                   (chdir "gpsbabel"))
-                 ;; TODO: "make doc" requires Docbook & co.
-                 %standard-phases)
+       #:phases
+       (modify-phases %standard-phases
+        (add-before 'configure 'pre-configure
+                    (lambda _
+                      (chdir "gpsbabel"))))
+                    ;; TODO: "make doc" requires Docbook & co.
 
        ;; On i686, 'raymarine.test' fails because of a rounding error:
        ;; <http://hydra.gnu.org/build/133040>.  As a workaround, disable tests
@@ -62,7 +63,7 @@
     (inputs
      `(("expat" ,expat)
        ("zlib" ,zlib)
-       ("qt4" ,qt-4)))
+       ("qt" ,qt)))
     (native-inputs
      `(("which" ,which)
        ("libxml2" ,libxml2)))              ;'xmllint' needed for the KML tests
diff --git a/gnu/packages/gstreamer.scm b/gnu/packages/gstreamer.scm
index 1235b3185a..45dded1a6e 100644
--- a/gnu/packages/gstreamer.scm
+++ b/gnu/packages/gstreamer.scm
@@ -28,21 +28,33 @@
   #:use-module (gnu packages audio)
   #:use-module (gnu packages bison)
   #:use-module (gnu packages cdrom)
+  #:use-module (gnu packages curl)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages flex)
+  #:use-module (gnu packages freedesktop)
+  #:use-module (gnu packages gl)
   #:use-module (gnu packages glib)
   #:use-module (gnu packages gnome)
+  #:use-module (gnu packages gnupg)
+  #:use-module (gnu packages graphics)
   #:use-module (gnu packages gtk)
   #:use-module (gnu packages image)
+  #:use-module (gnu packages libusb)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages mp3)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages pulseaudio)
+  #:use-module (gnu packages qt)
+  #:use-module (gnu packages rdf)
   #:use-module (gnu packages video)
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages xiph)
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages python)
+  #:use-module (gnu packages ssh)
+  #:use-module (gnu packages telephony)
+  #:use-module (gnu packages tls)
+  #:use-module (gnu packages version-control)
   #:use-module (gnu packages yasm)
   #:use-module (gnu packages xml))
 
@@ -52,7 +64,7 @@
     (version "0.4.24")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://gstreamer.freedesktop.org/data/src/"
+              (uri (string-append "https://gstreamer.freedesktop.org/data/src/"
                                   "orc/orc-" version ".tar.xz"))
               (sha256
                (base32
@@ -83,16 +95,16 @@ arrays of data.")
 (define-public gstreamer
   (package
     (name "gstreamer")
-    (version "1.6.1")
+    (version "1.6.3")
     (source
      (origin
       (method url-fetch)
       (uri (string-append
-            "http://gstreamer.freedesktop.org/src/gstreamer/gstreamer-"
+            "https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-"
             version ".tar.xz"))
       (sha256
        (base32
-        "172w1bpnkn6mm1wi37n03apdbb6cdkykhzjf1vfxchcd7hhkyflp"))))
+        "093zldafh7xh3lrlwzm7j0vvjz6k9ca83wqil40gfz5qcy6mdy92"))))
     (build-system gnu-build-system)
     (outputs '("out" "doc"))
     (arguments
@@ -113,7 +125,7 @@ arrays of data.")
      (list (search-path-specification
             (variable "GST_PLUGIN_SYSTEM_PATH")
             (files '("lib/gstreamer-1.0")))))
-    (home-page "http://gstreamer.freedesktop.org/")
+    (home-page "https://gstreamer.freedesktop.org/")
     (synopsis "Multimedia library")
     (description
      "GStreamer is a library for constructing graphs of media-handling
@@ -131,15 +143,15 @@ This package provides the core library and elements.")
 (define-public gst-plugins-base
   (package
     (name "gst-plugins-base")
-    (version "1.6.1")
+    (version "1.6.3")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "http://gstreamer.freedesktop.org/src/" name "/"
+      (uri (string-append "https://gstreamer.freedesktop.org/src/" name "/"
                           name "-" version ".tar.xz"))
       (sha256
        (base32
-        "18sbyjcp281zb3bsqji3pglsdsxi0s6ai7rx90sx8cpflkxdqcwm"))))
+        "0xbskifk95rw7jd85sqjrmqh2kys1bpi0inrxyapx1x4vf7ly5dn"))))
     (build-system gnu-build-system)
     (outputs '("out" "doc"))
     (propagated-inputs
@@ -168,12 +180,11 @@ This package provides the core library and elements.")
                             (assoc-ref %outputs "doc")
                             "/share/gtk-doc/html"))
        #:phases
-       (alist-cons-before
-        'configure 'patch
-        (lambda _
-          (substitute* "tests/check/libs/pbutils.c"
-            (("/bin/sh") (which "sh"))))
-        %standard-phases)))
+       (modify-phases %standard-phases
+         (add-before 'configure 'patch
+           (lambda _
+             (substitute* "tests/check/libs/pbutils.c"
+               (("/bin/sh") (which "sh"))))))))
     (home-page "http://gstreamer.freedesktop.org/")
     (synopsis
      "Plugins for the GStreamer multimedia library")
@@ -185,16 +196,16 @@ for the GStreamer multimedia library.")
 (define-public gst-plugins-good
   (package
     (name "gst-plugins-good")
-    (version "1.6.1")
+    (version "1.6.3")
     (source
      (origin
       (method url-fetch)
       (uri (string-append
-            "http://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-"
-            version ".tar.xz"))
+            "https://gstreamer.freedesktop.org/src/" name "/"
+            name "-" version ".tar.xz"))
       (sha256
        (base32
-        "0darc3058kbnql3mnlpizl0sq0hhli7vkm0rpqb7nywz14abim46"))))
+        "0xx16h0q63gs3pxlzdflnpyssba3vcrh1qnzplg4d0ra1fvrvc94"))))
     (build-system gnu-build-system)
     (inputs
      `(("aalib" ,aalib)
@@ -228,7 +239,7 @@ for the GStreamer multimedia library.")
           'unpack 'disable-failing-rtprtx-tests
           (lambda _
             ;; Disable rtprtx tests that frequently fail.
-            ;; XXX FIXME: Try removing this for version > 1.6.1.
+            ;; XXX FIXME: Try removing this for version > 1.6.3.
             (substitute* "tests/check/elements/rtprtx.c"
               (("tcase_add_test \\(tc_chain,\
  (test_rtxsender_max_size_packets|test_rtxreceive_data_reconstruction)\\);" all)
@@ -242,18 +253,91 @@ GStreamer multimedia library.  This set contains those plug-ins which the
 developers consider to have good quality code and correct functionality.")
     (license lgpl2.0+)))
 
+(define-public gst-plugins-bad
+  (package
+    (name "gst-plugins-bad")
+    (version "1.6.3")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://gstreamer.freedesktop.org/src/"
+                                  name "/" name "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "0q9s5da54819gwncmdi95l5qzx97l9vxk6adx4zmx73a3l82j6wp"))))
+    (outputs '("out" "doc"))
+    (build-system gnu-build-system)
+    (arguments
+     '(#:tests? #f ; XXX: 11 of 54 tests fail
+       #:configure-flags
+       (list (string-append "--with-html-dir="
+                            (assoc-ref %outputs "doc")
+                            "/share/gtk-doc/html"))))
+    (propagated-inputs
+     `(("gst-plugins-base" ,gst-plugins-base)))
+    (native-inputs
+     `(("glib:bin" ,glib "bin") ; for glib-mkenums, etc.
+       ("gobject-introspection" ,gobject-introspection)
+       ("pkg-config" ,pkg-config)
+       ("python" ,python)))
+    (inputs
+     ;; XXX: The following dependencies are missing:
+     ;;  vo-amrwbenc, vo-aacenc, bs2b, chromaprint, directfb, daala, libdts,
+     ;;  faac, flite, libgsm, libde265, libmms, libmimic, mjpegtools,
+     ;;  mpeg2enc, libofa, opencv, openh264, openni2, libtimemmgr, wildmidi,
+     ;;  openspc, gme, sbc, schroedinger, zbar, librtmp, spandsp, x265
+     `(("bluez" ,bluez)
+       ("curl" ,curl)
+       ("faad2" ,faad2)
+       ("fluidsynth" ,fluidsynth)
+       ("gtk+" ,gtk+)
+       ("ladspa" ,ladspa)
+       ("libass" ,libass)
+       ("libdvdnav" ,libdvdnav)
+       ("libdvdread" ,libdvdread)
+       ("libgcrypt" ,libgcrypt)
+       ("libgudev" ,libgudev)
+       ("libkate" ,libkate)
+       ("libmodplug" ,libmodplug)
+       ("librsvg" ,librsvg)
+       ("libsndfile" ,libsndfile)
+       ("libsrtp" ,libsrtp)
+       ("libssh2" ,libssh2)
+       ("libusb" ,libusb)
+       ("libvdpau" ,libvdpau)
+       ("libwebp" ,libwebp)
+       ("libxml2" ,libxml2)
+       ("lrdf" ,lrdf)
+       ("mesa" ,mesa)
+       ("mpg123" ,mpg123)
+       ("neon" ,neon)
+       ("openal" ,openal)
+       ("openexr" ,openexr)
+       ("openjpeg" ,openjpeg)
+       ("openssl" ,openssl)
+       ("opus" ,opus)
+       ("orc" ,orc)
+       ("qt" ,qt)
+       ("soundtouch" ,soundtouch)
+       ("wayland" ,wayland)))
+    (home-page "http://gstreamer.freedesktop.org/")
+    (synopsis "Plugins for the GStreamer multimedia library")
+    (description
+     "GStreamer Bad Plug-ins is a set of plug-ins whose quality aren't up to
+par compared to the rest.")
+    (license lgpl2.0+)))
+
 (define-public gst-plugins-ugly
   (package
     (name "gst-plugins-ugly")
-    (version "1.6.1")
+    (version "1.6.3")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "http://gstreamer.freedesktop.org/src/"
+       (uri (string-append "https://gstreamer.freedesktop.org/src/"
                            name "/" name "-" version ".tar.xz"))
        (sha256
         (base32
-         "0mvasl1pwq70w2kmrkcrg77kggl5q7jqybi7fkvy3vr28c7gkhqc"))))
+         "0r6h3ys5n90jv3c06crxzcac561z07s4h04hy5i8ybw8qyvzgv1g"))))
     (build-system gnu-build-system)
     (inputs
      `(("gst-plugins-base" ,gst-plugins-base)
@@ -283,15 +367,15 @@ distribution problems in some jurisdictions, e.g. due to patent threats.")
 (define-public gst-libav
   (package
     (name "gst-libav")
-    (version "1.6.1")
+    (version "1.6.3")
     (source (origin
               (method url-fetch)
               (uri (string-append
-                    "http://gstreamer.freedesktop.org/src/" name "/"
+                    "https://gstreamer.freedesktop.org/src/" name "/"
                     name "-" version ".tar.xz"))
               (sha256
                (base32
-                "1a9pc7zp5rg0cvpx8gqkr21w73i6p9xa505a34day9f8p3lfim94"))))
+                "1aylbg1xnm68c3wc49mzx813qhsjfg23hqnjqqwdwdq31839qyw5"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags '("--with-system-libav")
diff --git a/gnu/packages/gtk.scm b/gnu/packages/gtk.scm
index 6e2a67d25c..1a10e9b551 100644
--- a/gnu/packages/gtk.scm
+++ b/gnu/packages/gtk.scm
@@ -150,7 +150,7 @@ affine transformation (scale, rotation, shear, etc.).")
    (version "1.0.6")
    (source (origin
              (method url-fetch)
-             (uri (string-append "http://www.freedesktop.org/software/"
+             (uri (string-append "https://www.freedesktop.org/software/"
                                  "harfbuzz/release/harfbuzz-"
                                  version ".tar.bz2"))
              (sha256
@@ -365,7 +365,7 @@ printing and other features typical of a source code editor.")
    (native-inputs
     `(("glib:bin" ,glib "bin") ; for glib-genmarshal, etc.
       ("intltool" ,intltool)
-      ("itstool", itstool)
+      ("itstool" ,itstool)
       ("gobject-introspection" ,gobject-introspection)
       ("pkg-config" ,pkg-config)
       ("vala" ,vala)
@@ -425,7 +425,7 @@ highlighting and other features typical of a source code editor.")
    (native-inputs
      `(("pkg-config" ,pkg-config)
        ("glib" ,glib "bin")                               ; glib-mkenums, etc.
-       ("gobject-introspection", gobject-introspection))) ; g-ir-compiler, etc.
+       ("gobject-introspection" ,gobject-introspection))) ; g-ir-compiler, etc.
    (synopsis "GNOME image loading and manipulation library")
    (description
     "GdkPixbuf is a library for image loading and manipulation developed
@@ -1013,6 +1013,7 @@ extensive documentation, including API reference and a tutorial.")
      `(("pkg-config" ,pkg-config)))
     (inputs
      `(("python" ,python-2)
+       ("libglade" ,libglade)
        ("glib"   ,glib)))
     (propagated-inputs
      `(("python-pycairo"   ,python2-pycairo)     ;loaded at runtime
@@ -1107,7 +1108,25 @@ information.")
                 "12xmmcnq4138dlbhmqa45wqza8dky4lf856sp80h6xjwl2g7a85l"))))
     (build-system gnu-build-system)
     (arguments
-     `(#:configure-flags
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-before
+             'configure 'fix-docbook
+           (lambda* (#:key inputs #:allow-other-keys)
+             (substitute* "configure"
+               ;; The configure check is overzealous about making sure that
+               ;; things are in place -- it uses the xmlcatalog tool to make
+               ;; sure that docbook-xsl is available, but this tool can only
+               ;; look in one catalog file, unlike the $XML_CATALOG_FILES
+               ;; variable that Guix defines.  Fool the test by using the
+               ;; docbook-xsl catalog explicitly and get on with life.
+               (("\"\\$XML_CATALOG_FILE\" \
+\"http://docbook.sourceforge.net/release/xsl/")
+                (string-append (car (find-files (assoc-ref inputs "docbook-xsl")
+                                                "^catalog.xml$"))
+                               " \"http://docbook.sourceforge.net/release/xsl/")))
+             #t)))
+       #:configure-flags
        (list (string-append "--with-xml-catalog="
                             (assoc-ref %build-inputs "docbook-xml")
                             "/xml/dtd/docbook/catalog.xml"))))
diff --git a/gnu/packages/guile.scm b/gnu/packages/guile.scm
index 6cbca7a478..5349fda081 100644
--- a/gnu/packages/guile.scm
+++ b/gnu/packages/guile.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Christopher Allan Webber <cwebber@dustycloud.org>
+;;; Copyright © 2016 Alex Sassmannshausen <alex@pompo.co>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -210,7 +211,15 @@ without requiring the source code to be rewritten.")
               ;; times (almost 3 hours on a 4-core Intel i5).
               (snippet '(for-each delete-file
                                   (find-files "prebuilt" "\\.go$")))))
-    (synopsis "Snapshot of what will become version 2.2 of GNU Guile")))
+    (synopsis "Snapshot of what will become version 2.2 of GNU Guile")
+    (native-search-paths
+     (list (search-path-specification
+            (variable "GUILE_LOAD_PATH")
+            (files '("share/guile/site/2.2")))
+           (search-path-specification
+            (variable "GUILE_LOAD_COMPILED_PATH")
+            (files '("lib/guile/2.2/ccache"
+                     "share/guile/site/2.2")))))))
 
 (define-public guile-for-guile-emacs
   (package (inherit guile-next)
@@ -440,14 +449,14 @@ for Guile\".")
 (define-public guile-json
   (package
     (name "guile-json")
-    (version "0.4.0")
+    (version "0.5.0")
     (source (origin
              (method url-fetch)
              (uri (string-append "mirror://savannah/guile-json/guile-json-"
                                  version ".tar.gz"))
              (sha256
               (base32
-               "0v06272rw4ycwzssjf3fzpk2vhpslvl55hz94q80vc6f74j0d5h6"))
+               "0l8a34l92nrdszy7ykycfvr8y0n0yi5qb3ccliycvpvf9mzk5n8d"))
              (modules '((guix build utils)))
              (snippet
               ;; Make sure everything goes under .../site/2.0, like Guile's
@@ -700,6 +709,28 @@ Guile's foreign function interface.")
                (base32
                 "15q1qwjnay7k90ppqrzqsmikvwyj61mjvf1zahyd9gm4vi2fgb3x"))))
     (build-system gnu-build-system)
+    (arguments
+     `(#:modules ((ice-9 match) (ice-9 ftw)
+                  ,@%gnu-build-system-modules)
+
+       #:phases (modify-phases %standard-phases
+                  (add-after 'install 'wrap-haunt
+                    (lambda* (#:key outputs #:allow-other-keys)
+                      ;; Wrap the 'haunt' command to refer to the right
+                      ;; modules.
+                      (let* ((out  (assoc-ref outputs "out"))
+                             (bin  (string-append out "/bin"))
+                             (site (string-append
+                                    out "/share/guile/site")))
+                        (match (scandir site)
+                          (("." ".." version)
+                           (let ((modules (string-append site "/" version)))
+                             (wrap-program (string-append bin "/haunt")
+                               `("GUILE_LOAD_PATH" ":" prefix
+                                 (,modules))
+                               `("GUILE_LOAD_COMPILED_PATH" ":" prefix
+                                 (,modules)))
+                             #t)))))))))
     (inputs
      `(("guile" ,guile-2.0)))
     (synopsis "Functional static site generator")
@@ -709,6 +740,33 @@ interface for reading articles in any format.")
     (home-page "http://haunt.dthompson.us")
     (license gpl3+)))
 
+(define-public guile-config
+  (package
+    (name "guile-config")
+    (version "0.1.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "http://alex.pompo.co/software/" name "-" version
+                    ".tar.gz"))
+              (sha256
+               (base32
+                "1b719bn192f9wg24rr0zx8jpmygsvyhfi35iy778pb5p392snrn8"))))
+    (build-system gnu-build-system)
+    (inputs
+     `(("guile" ,guile-2.0)))
+    (synopsis "Guile application configuration parsing library")
+    (description
+     "Guile Config is a library providing a declarative approach to
+application configuration specification.  The library provides clean
+configuration declaration forms, and processors that take care of:
+configuration file creation; configuration file parsing; command-line
+parameter parsing using getopt-long; basic GNU command-line parameter
+generation (--help, --usage, --version); automatic output generation for the
+above command-line parameters.")
+    (home-page "https://github.com/a-sassmannshausen/guile-config")
+    (license agpl3+)))
+
 (define-public guile-redis
   (package
     (name "guile-redis")
diff --git a/gnu/packages/icu4c.scm b/gnu/packages/icu4c.scm
index d442b5e69a..a6f5acd4f2 100644
--- a/gnu/packages/icu4c.scm
+++ b/gnu/packages/icu4c.scm
@@ -31,11 +31,12 @@
    (version "55.1")
    (source (origin
             (method url-fetch)
-            (uri (string-append "http://download.icu-project.org/files/icu4c/"
-                   version
-                   "/icu4c-"
-                   (string-map (lambda (x) (if (char=? x #\.) #\_ x)) version)
-                   "-src.tgz"))
+            (uri (string-append
+                  "mirror://sourceforge/icu/ICU4C/"
+                  version
+                  "/icu4c-"
+                  (string-map (lambda (x) (if (char=? x #\.) #\_ x)) version)
+                  "-src.tgz"))
             (sha256
              (base32 "0ys5f5spizg45qlaa31j2lhgry0jka2gfha527n4ndfxxz5j4sz1"))
             (patches (map search-patch '("icu4c-CVE-2014-6585.patch"
diff --git a/gnu/packages/kde-frameworks.scm b/gnu/packages/kde-frameworks.scm
index 5e73a6b7fa..ec637e55d1 100644
--- a/gnu/packages/kde-frameworks.scm
+++ b/gnu/packages/kde-frameworks.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -26,7 +27,7 @@
   #:use-module (gnu packages qt)
   #:use-module (gnu packages xorg))
 
-(define kde-frameworks-version "5.12.0")
+(define kde-frameworks-version "5.19.0")
 
 (define-public extra-cmake-modules
   (package
@@ -39,7 +40,8 @@
                             (version-major+minor version) "/"
                             name "-" version ".tar.xz"))
         (sha256
-          (base32 "14n77sn493m8kzr42wv13mdgxpnbx7x64bvw37ircrx8wmf4002i"))))
+         (base32
+          "1dl3hhbara7iswb5wsc5dp17ar3ljw5f0nrncl8vry9smaz2zl63"))))
     ;; 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.
@@ -63,18 +65,19 @@ common build settings used in software produced by the KDE community.")
                             (version-major+minor version) "/"
                             name "-" version ".tar.xz"))
         (sha256
-          (base32 "0fjxhf07r186cmp0mjvinrwxg4z90zlyvycqhy0n18fdp67szckl"))))
+         (base32
+          "115xs34r74j9zcsw69glnh8w59iyh764n3gniawwrk23c6yb8fch"))))
     (build-system cmake-build-system)
     (native-inputs
-      `(("pkg-config" ,pkg-config)
-        ("xorg-server" ,xorg-server))) ; for the tests
+     `(("pkg-config" ,pkg-config)
+       ("xorg-server" ,xorg-server))) ; for the tests
     (inputs
-      `(("extra-cmake-modules" ,extra-cmake-modules)
-        ("libxrender" ,libxrender)
-        ("qt" ,qt)
-        ("xcb-utils-keysyms" ,xcb-util-keysyms)))
+     `(("extra-cmake-modules" ,extra-cmake-modules)
+       ("libxrender" ,libxrender)
+       ("qt" ,qt)
+       ("xcb-utils-keysyms" ,xcb-util-keysyms)))
     (arguments
-      `(#:tests? #f)) ; FIXME: The first seven tests fail with "Exception".
+     `(#:tests? #f)) ; FIXME: The first seven tests fail with "Exception".
     (home-page "https://community.kde.org/Frameworks")
     (synopsis "KDE access to the windowing system")
     (description "KWindowSystem provides information about and allows
diff --git a/gnu/packages/kde.scm b/gnu/packages/kde.scm
deleted file mode 100644
index 1409e7c0b1..0000000000
--- a/gnu/packages/kde.scm
+++ /dev/null
@@ -1,229 +0,0 @@
-;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015 Andreas Enge <andreas@enge.fr>
-;;;
-;;; 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 kde)
-  #:use-module ((guix licenses) #:select (bsd-2 lgpl2.0+ lgpl2.1 lgpl2.1+ lgpl3+))
-  #:use-module (guix packages)
-  #:use-module (guix download)
-  #:use-module (guix build-system cmake)
-  #:use-module (gnu packages compression)
-  #:use-module (gnu packages doxygen)
-  #:use-module (gnu packages geeqie)
-  #:use-module (gnu packages glib)
-  #:use-module (gnu packages perl)
-  #:use-module (gnu packages pkg-config)
-  #:use-module (gnu packages pulseaudio)
-  #:use-module (gnu packages python)
-  #:use-module (gnu packages qt)
-  #:use-module (gnu packages rdf)
-  #:use-module (gnu packages ruby)
-  #:use-module (gnu packages video)
-  #:use-module (gnu packages xml)
-  #:use-module (gnu packages xorg))
-
-(define-public automoc4
-  (package
-    (name "automoc4")
-    (version "0.9.88")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "http://download.kde.org/stable/" name
-                                "/" version "/" name "-"
-                                 version ".tar.bz2"))
-             (sha256
-              (base32
-               "0jackvg0bdjg797qlbbyf9syylm0qjs55mllhn11vqjsq3s1ch93"))))
-    (build-system cmake-build-system)
-    (inputs
-     `(("qt" ,qt-4)))
-    (arguments
-     `(#:tests? #f)) ; no check target
-    (home-page "http://techbase.kde.org/Development/Tools/Automoc4")
-    (synopsis "Build tool for KDE")
-    (description "AutoMoc4 automatically generates moc-files for KDE.")
-    (license bsd-2)))
-
-(define-public phonon
-  (package
-    (name "phonon")
-    (version "4.8.3")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "http://download.kde.org/stable/" name
-                                "/" version "/src/"
-                                name "-" version ".tar.xz"))
-             (sha256
-              (base32
-               "05nshngk03ln90vsjz44dx8al576f4vd5fvhs1l0jmx13jb9q551"))))
-    (build-system cmake-build-system)
-    ;; FIXME: Add optional input libqzeitgeist once available.
-    (native-inputs
-     `(("automoc4" ,automoc4)
-       ("pkg-config" ,pkg-config)))
-    (inputs
-     `(("glib" ,glib)
-       ("libx11" ,libx11)
-       ("pulseaudio" ,pulseaudio)))
-    (propagated-inputs
-     `(("qt" ,qt-4))) ; according to phonon.pc
-    (arguments
-     `(#:tests? #f)) ; no test target
-    (home-page "http://phonon.kde.org/")
-    (synopsis "Qt 4 multimedia API")
-    (description "KDE desktop environment")
-    (license lgpl2.1+)))
-
-(define-public qjson
-  (package
-    (name "qjson")
-    (version "0.8.1")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "https://github.com/flavio/qjson/archive/"
-                                 version ".tar.gz"))
-             (file-name (string-append name "-" version ".tar.gz"))
-             (sha256
-              (base32
-               "163fspi0xc705irv79qw861fmh68pjyla9vx3kqiq6xrdhb9834j"))))
-    (build-system cmake-build-system)
-    (inputs
-     `(("qt" ,qt-4)))
-    (arguments
-     `(#:tests? #f)) ; no test target
-    (home-page "http://qjson.sourceforge.net/")
-    (synopsis "Qt-based library for handling JSON")
-    (description "QJson is a Qt-based library that maps JSON data to QVariant
-objects and vice versa.  JSON arrays are mapped to QVariantList instances,
-while JSON objects are mapped to QVariantMap.")
-    (license lgpl2.1+)))
-
-(define-public libdbusmenu-qt
-  (package
-    (name "libdbusmenu-qt")
-    (version "0.9.2")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "https://launchpad.net/" name "/trunk/"
-                                 version "/+download/"
-                                 name "-" version ".tar.bz2"))
-             (sha256
-              (base32
-               "1v0ri5g9xw2z64ik0kx0ra01v8rpjn2kxprrxppkls1wvav1qv5f"))))
-    (build-system cmake-build-system)
-    (native-inputs
-     `(("doxygen" ,doxygen) ; used for static documentation
-       ("pkg-config" ,pkg-config)
-       ("qjson", qjson))) ; used for the tests
-    (inputs
-     `(("qt" ,qt-4)))
-    (arguments
-     `(#:tests? #f)) ; no check target
-    (home-page "https://launchpad.net/libdbusmenu-qt/")
-    (synopsis "Qt implementation of the DBusMenu protocol")
-    (description "The library provides a Qt implementation of the DBusMenu
-protocol.  The DBusMenu protocol makes it possible for applications to export
-and import their menus over DBus.")
-    (license lgpl2.0+)))
-
-(define-public attica
-  (package
-    (name "attica")
-    (version "0.4.2")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "http://download.kde.org/stable/"
-                                 name "/"
-                                 name "-" version ".tar.bz2"))
-             (sha256
-              (base32
-               "1y74gsyzi70dfr9d1f1b08k130rm3jaibsppg8dv5h3211vm771v"))))
-    (build-system cmake-build-system)
-    (inputs
-     `(("qt" ,qt-4)))
-    (home-page "https://projects.kde.org/projects/frameworks/attica")
-    (synopsis "Qt library for the Open Collaboration Services API")
-    (description "Attica is a Qt library that implements the Open
-Collaboration Services API version 1.6.  It grants easy access to the
-services such as querying information about persons and contents.  The
-library is used in KNewStuff3 as content provider.  In order to integrate
-with KDE's Plasma Desktop, a platform plugin exists in kdebase.")
-    (license lgpl2.1+)))
-
-(define-public strigi
-  (package
-    (name "strigi")
-    (version "0.7.8")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "http://www.vandenoever.info/software/"
-                                 name "/"
-                                 name "-" version ".tar.bz2"))
-             (sha256
-              (base32
-               "12grxzqwnvbyqw7q1gnz42lypadxmq89vk2qpxczmpmc4nk63r23"))))
-    (build-system cmake-build-system)
-    (native-inputs
-     `(("pkg-config" ,pkg-config)))
-    ;; FIXME: Add optional inputs XAttr, FAM, Log4cxx
-    (inputs
-     `(("clucene" ,clucene)
-       ("dbus" ,dbus)
-       ("exiv2" ,exiv2)
-       ("ffmpeg" ,ffmpeg)
-       ("libxml2" ,libxml2)
-       ("perl" ,perl)
-       ("python" ,python-wrapper)
-       ("qt" ,qt-4)
-       ("zlib" ,zlib)))
-    (arguments
-     `(#:tests? #f)) ; FIXME: Test 23/25 ProcessInputStreamTest fails.
-    (home-page "http://www.vandenoever.info/software/strigi/")
-    (synopsis "Desktop search daemon")
-    (description "Strigi is a desktop search daemon with the following
-main features:
-very fast crawling;
-very small memory footprint;
-no hammering of the system;
-pluggable backend, currently clucene and hyperestraier, sqlite3 and xapian
-are in the works;
-communication between daemon and search program over an abstract interface,
-currently a simple socket;
-simple interface for implementing plugins for extracting information;
-calculation of sha1 for every file crawled
-(allows fast finding of duplicates).")
-    (license lgpl2.0+)))
-
-(define-public oxygen-icons
-  (package
-    (name "oxygen-icons")
-    (version "4.14.2")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "http://download.kde.org/stable/" version
-                                "/src/" name "-"
-                                 version ".tar.xz"))
-             (sha256
-              (base32
-               "1mz73f54qh2vd8ibp60f6fjflrprz0lvqfkgh805l7wfhrv4ckbz"))))
-    (build-system cmake-build-system)
-    (arguments
-     `(#:tests? #f)) ; no test target
-    (home-page "http://www.kde.org/")
-    (synopsis "Oxygen icon theme for the KDE desktop")
-    (description "KDE desktop environment")
-    (license lgpl3+)))
diff --git a/gnu/packages/ldc.scm b/gnu/packages/ldc.scm
index 1981bc115d..66da63581c 100644
--- a/gnu/packages/ldc.scm
+++ b/gnu/packages/ldc.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015 Roel Janssen <roel@gnu.org>
+;;; Copyright © 2015, 2016 Roel Janssen <roel@gnu.org>
 ;;; Copyright © 2015 Pjotr Prins <pjotr.guix@thebird.nl>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -21,6 +21,8 @@
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix packages)
   #:use-module (guix download)
+  #:use-module (guix git-download)
+  #:use-module (guix build-system gnu)
   #:use-module (guix build-system cmake)
   #:use-module (gnu packages)
   #:use-module (gnu packages base)
@@ -29,6 +31,47 @@
   #:use-module (gnu packages textutils)
   #:use-module (gnu packages zip))
 
+(define-public rdmd
+  (let ((commit "da0a2e0a379b08294015eec9d531f1e5dd4226f0"))
+    (package
+      (name "rdmd")
+      (version (string-append "v2.070.0-1." (string-take commit 7)))
+      (source (origin
+        (method git-fetch)
+        (uri (git-reference
+              (url "https://github.com/D-Programming-Language/tools.git")
+              (commit commit)))
+        (file-name (string-append name "-" version "-checkout"))
+        (sha256
+         (base32
+          "1pcx5lyqzrip86f4vv60x292rpvnwsq2hvl1znm9x9rn68f34m45"))))
+      (build-system gnu-build-system)
+      (arguments
+       '(#:phases
+         (modify-phases %standard-phases
+           (delete 'configure)
+           (delete 'check) ; There is no Makefile, so there's no 'make check'.
+           (replace
+            'build
+            (lambda _
+              (zero? (system* "ldc2" "rdmd.d"))))
+           (replace
+            'install
+            (lambda* (#:key outputs #:allow-other-keys)
+              (let ((bin (string-append (assoc-ref outputs "out") "/bin")))
+                (install-file "rdmd" bin)))))))
+      (native-inputs
+       `(("ldc" ,ldc)))
+      (home-page "https://github.com/D-Programming-Language/tools/")
+      (synopsis "Specialized equivalent to 'make' for the D language")
+      (description
+       "rdmd is a companion to the dmd compiler that simplifies the typical
+edit-compile-link-run or edit-make-run cycle to a rapid edit-run cycle.  Like
+make and other tools, rdmd uses the relative dates of the files involved to
+minimize the amount of work necessary.  Unlike make, rdmd tracks dependencies
+and freshness without requiring additional information from the user.")
+      (license license:boost1.0))))
+
 (define-public ldc
   (package
     (name "ldc")
diff --git a/gnu/packages/libcanberra.scm b/gnu/packages/libcanberra.scm
index 50c0f80eed..bfa7715160 100644
--- a/gnu/packages/libcanberra.scm
+++ b/gnu/packages/libcanberra.scm
@@ -110,7 +110,7 @@ null) and is designed to be portable.")
     (version "0.8")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://people.freedesktop.org/~mccann/dist/"
+              (uri (string-append "https://people.freedesktop.org/~mccann/dist/"
                                   name "-" version ".tar.bz2"))
               (sha256
                (base32
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 9bfdc66f46..414570eccd 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -7,6 +7,8 @@
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
+;;; Copyright © 2016 Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>
+;;; Copyright © 2016 Alex Kost <alezost@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -218,7 +220,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.4.1")
+  (let* ((version "4.4.3")
          (build-phase
           '(lambda* (#:key system inputs #:allow-other-keys #:rest args)
              ;; Apply the neat patch.
@@ -292,7 +294,7 @@ for SYSTEM and optionally VARIANT, or #f if there is no such configuration."
              (uri (linux-libre-urls version))
              (sha256
               (base32
-               "1d6wzhbpz0g79iwlkv10qmig518risz9bi3qw8wdn7j2xs7ij1j2"))))
+               "06wl6gvhds6j6aaryzpz4jngdf3v70spvp1xb7k2c03kvm9v5f4v"))))
     (build-system gnu-build-system)
     (supported-systems '("x86_64-linux" "i686-linux"))
     (native-inputs `(("perl" ,perl)
@@ -327,13 +329,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.17")
+    (version "4.1.18")
     (source (origin
               (method url-fetch)
               (uri (linux-libre-urls version))
               (sha256
                (base32
-                "0mkvj5sab8l2k0mgfca3y4n5g9cxs3px0ysvdwa2zwl52n7dsfk4"))))
+                "1bddh2rg645lavhjkk9z75vflba5y0g73z2fjwgbfrj5jb44x9i7"))))
     (native-inputs
      (let ((conf (kernel-config (or (%current-target-system)
                                     (%current-system))
@@ -794,14 +796,14 @@ MIDI functionality to the Linux-based operating system.")
 (define-public alsa-utils
   (package
     (name "alsa-utils")
-    (version "1.0.27.2")
+    (version "1.1.0")
     (source (origin
              (method url-fetch)
-             (uri (string-append "ftp://ftp.alsa-project.org/pub/utils/alsa-utils-"
-                                 version ".tar.bz2"))
+             (uri (string-append "ftp://ftp.alsa-project.org/pub/utils/"
+                                 name "-" version ".tar.bz2"))
              (sha256
               (base32
-               "1sjjngnq50jv5ilwsb4zys6smifni3bd6fn28gbnhfrg14wsrgq2"))))
+               "1wa88wvqcfhak9x3y65wzzwxmmyxb5bv2gyj7lnm653fnwsk271v"))))
     (build-system gnu-build-system)
     (arguments
      ;; XXX: Disable man page creation until we have DocBook.
@@ -867,15 +869,15 @@ packet filter.")
 (define-public iproute
   (package
     (name "iproute2")
-    (version "3.12.0")
+    (version "4.4.0")
     (source (origin
-             (method url-fetch)
-             (uri (string-append
-                   "mirror://kernel.org/linux/utils/net/iproute2/iproute2-"
-                   version ".tar.xz"))
-             (sha256
-              (base32
-               "04gi11gh087bg2nlxhj0lxrk8l9qxkpr88nsiil23917bm3h1xj4"))))
+              (method url-fetch)
+              (uri (string-append
+                    "mirror://kernel.org/linux/utils/net/iproute2/iproute2-"
+                    version ".tar.xz"))
+              (sha256
+               (base32
+                "05351m4m0whsivlblvs3m0nz5q9v6r06ik80z27gf6ca51kw74dw"))))
     (build-system gnu-build-system)
     (arguments
      `(#:tests? #f                                ; no test suite
@@ -887,13 +889,12 @@ packet filter.")
                             (string-append "DOCDIR=" out "/share/doc/"
                                            ,name "-" ,version)
                             (string-append "MANDIR=" out "/share/man")))
-       #:phases (alist-cons-before
-                 'install 'pre-install
-                 (lambda _
-                   ;; Don't attempt to create /var/lib/arpd.
-                   (substitute* "Makefile"
-                     (("^.*ARPDDIR.*$") "")))
-                 %standard-phases)))
+       #:phases (modify-phases %standard-phases
+                  (add-before 'install 'pre-install
+                    (lambda _
+                      ;; Don't attempt to create /var/lib/arpd.
+                      (substitute* "Makefile"
+                        (("^.*ARPDDIR.*$") "")))))))
     (inputs
      `(("iptables" ,iptables)
        ("db4" ,bdb)))
@@ -2467,3 +2468,40 @@ write access to exFAT devices.")
 applications running on the Linux console.  It allows users to select items
 and copy/paste text in the console and in xterm.")
     (license license:gpl2+)))
+
+(define-public btrfs-progs
+  (package
+    (name "btrfs-progs")
+    (version "4.4")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://kernel.org/linux/kernel/"
+                                  "people/kdave/btrfs-progs/"
+                                  "btrfs-progs-v" version ".tar.xz"))
+              (sha256
+               (base32
+                "0jssv1ys4nw2jf7mkp58c19yspaa8ybf48fxsrhhp0683mzpr73p"))))
+    (build-system gnu-build-system)
+    (arguments
+     '(#:test-target "test"
+       #:parallel-tests? #f)) ; tests fail when run in parallel
+    (inputs `(("e2fsprogs" ,e2fsprogs)
+              ("libblkid" ,util-linux)
+              ("libuuid" ,util-linux)
+              ("zlib" ,zlib)
+              ("lzo" ,lzo)))
+    (native-inputs `(("pkg-config" ,pkg-config)
+                     ("asciidoc" ,asciidoc)
+                     ("xmlto" ,xmlto)
+                     ;; For building documentation
+                     ("libxml2" ,libxml2)
+                     ("docbook-xml" ,docbook-xml)
+                     ("docbook-xsl" ,docbook-xsl)))
+    (home-page "https://btrfs.wiki.kernel.org/")
+    (synopsis "Create and manage btrfs copy-on-write file systems")
+    (description "Btrfs is a copy-on-write (CoW) filesystem for Linux aimed at
+implementing advanced features while focusing on fault tolerance, repair and
+easy administration.")
+    ;; GPL2+: crc32.c, radix-tree.c, raid6.c, rbtree.c.
+    ;; GPL2: Everything else.
+    (license (list license:gpl2 license:gpl2+))))
diff --git a/gnu/packages/lsh.scm b/gnu/packages/lsh.scm
index e034d66940..3b6487f38c 100644
--- a/gnu/packages/lsh.scm
+++ b/gnu/packages/lsh.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.
 ;;;
@@ -29,7 +29,8 @@
   #:use-module (gnu packages multiprecision)
   #:use-module (gnu packages readline)
   #:use-module (gnu packages gperf)
-  #:use-module (gnu packages guile))
+  #:use-module (gnu packages guile)
+  #:use-module (gnu packages xorg))
 
 (define-public liboop
   (package
@@ -100,7 +101,11 @@ basis for almost any application.")
 
        ("liboop" ,liboop)
        ("zlib" ,guix:zlib)
-       ("gmp" ,gmp)))
+       ("gmp" ,gmp)
+
+       ;; The server (lshd) invokes xauth when X11 forwarding is requested.
+       ;; This adds 24 MiB (or 27%) to the closure of lsh.
+       ("xauth" ,xauth)))
     (arguments
      '(;; Skip the `configure' test that checks whether /dev/ptmx &
        ;; co. work as expected, because it relies on impurities (for
@@ -113,26 +118,36 @@ basis for almost any application.")
        #:tests? #f
 
        #:phases
-       (alist-cons-before
-        'configure 'pre-configure
-        (lambda* (#:key inputs #:allow-other-keys)
-          (let* ((nettle    (assoc-ref inputs "nettle"))
-                 (sexp-conv (string-append nettle "/bin/sexp-conv")))
-            ;; Make sure 'lsh' and 'lshd' pick 'sexp-conv' in the right place
-            ;; by default.
-            (substitute* "src/environ.h.in"
-              (("^#define PATH_SEXP_CONV.*")
-               (string-append "#define PATH_SEXP_CONV \""
-                              sexp-conv "\"\n")))
+       (modify-phases %standard-phases
+         (add-before 'configure 'pre-configure
+           (lambda* (#:key inputs #:allow-other-keys)
+             (let* ((nettle    (assoc-ref inputs "nettle"))
+                    (sexp-conv (string-append nettle "/bin/sexp-conv")))
+               ;; Make sure 'lsh' and 'lshd' pick 'sexp-conv' in the right place
+               ;; by default.
+               (substitute* "src/environ.h.in"
+                 (("^#define PATH_SEXP_CONV.*")
+                  (string-append "#define PATH_SEXP_CONV \""
+                                 sexp-conv "\"\n")))
+
+               ;; Same for the 'lsh-authorize' script.
+               (substitute* "src/lsh-authorize"
+                 (("=sexp-conv")
+                  (string-append "=" sexp-conv)))
 
-            ;; Same for the 'lsh-authorize' script.
-            (substitute* "src/lsh-authorize"
-              (("=sexp-conv")
-               (string-append "=" sexp-conv))))
+               ;; Tell lshd where 'xauth' lives.  Another option would be to
+               ;; hardcode "/run/current-system/profile/bin/xauth", thereby
+               ;; reducing the closure size, but that wouldn't work on foreign
+               ;; distros.
+               (with-fluids ((%default-port-encoding "ISO-8859-1"))
+                 (substitute* "src/server_x11.c"
+                   (("define XAUTH_PROGRAM.*")
+                    (string-append "define XAUTH_PROGRAM \""
+                                   (assoc-ref inputs "xauth")
+                                   "/bin/xauth\"\n")))))
 
-          ;; Tests rely on $USER being set.
-          (setenv "USER" "guix"))
-        %standard-phases)))
+             ;; Tests rely on $USER being set.
+             (setenv "USER" "guix"))))))
     (home-page "http://www.lysator.liu.se/~nisse/lsh/")
     (synopsis "GNU implementation of the Secure Shell (ssh) protocols")
     (description
diff --git a/gnu/packages/lua.scm b/gnu/packages/lua.scm
index d27c024cfb..fcb41831eb 100644
--- a/gnu/packages/lua.scm
+++ b/gnu/packages/lua.scm
@@ -40,7 +40,7 @@
              (patches (list (search-patch "lua-pkgconfig.patch")
                             (search-patch "lua52-liblua-so.patch")))))
     (build-system gnu-build-system)
-    (inputs `(("readline", readline)))
+    (inputs `(("readline" ,readline)))
     (arguments
      '(#:modules ((guix build gnu-build-system)
                     (guix build utils)
diff --git a/gnu/packages/lxqt.scm b/gnu/packages/lxqt.scm
index d840ff0098..677b580bed 100644
--- a/gnu/packages/lxqt.scm
+++ b/gnu/packages/lxqt.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
+;;; Copyright © 2016 Mark H Weaver <mhw@netris.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -36,7 +37,7 @@
      (origin
        (method url-fetch)
        (uri
-         (string-append "http://downloads.lxqt.org/libqtxdg/" version "/"
+         (string-append "https://downloads.lxqt.org/libqtxdg/" version "/"
                         name "-" version ".tar.xz"))
        (sha256
         (base32
@@ -63,7 +64,7 @@ in Qt.")
      (origin
        (method url-fetch)
        (uri
-         (string-append "http://downloads.lxqt.org/lxqt/" version "/"
+         (string-append "https://downloads.lxqt.org/lxqt/" version "/"
                         name "-" version ".tar.xz"))
        (sha256
         (base32
@@ -91,7 +92,7 @@ components of the LXQt desktop environment.")
      (origin
        (method url-fetch)
        (uri
-         (string-append "http://downloads.lxqt.org/lxqt/" version "/"
+         (string-append "https://downloads.lxqt.org/lxqt/" version "/"
                         name "-" version ".tar.xz"))
        (sha256
         (base32
@@ -142,7 +143,7 @@ desktop environment.")
      (origin
        (method url-fetch)
        (uri
-         (string-append "http://downloads.lxqt.org/lxqt/" version "/"
+         (string-append "https://downloads.lxqt.org/lxqt/" version "/"
                         name "-" version ".tar.xz"))
        (sha256
         (base32
diff --git a/gnu/packages/mail.scm b/gnu/packages/mail.scm
index d41479e83f..5a9f420b43 100644
--- a/gnu/packages/mail.scm
+++ b/gnu/packages/mail.scm
@@ -10,6 +10,7 @@
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
+;;; Copyright © 2016 Al McElrath <hello@yrns.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -414,6 +415,47 @@ attachments, create new maildirs, and so on.")
 ing, and tagging large collections of email messages.")
     (license gpl3+)))
 
+(define-public notmuch-addrlookup-c
+  (package
+    (name "notmuch-addrlookup-c")
+    (version "7")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://github.com/aperezdc/" name "/archive/v"
+                    version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0rslg2ifgyhl6asv3yr1f62m9xjfcinv7i6qb07h2k217jqlmrri"))))
+    (build-system gnu-build-system)
+    (arguments
+     '(#:tests? #f ; no tests
+       #:make-flags (list "CC=gcc"
+                          (string-append "PREFIX="
+                                         (assoc-ref %outputs "out")))
+       #:phases (modify-phases %standard-phases
+                  (delete 'configure)
+                  ;; Remove vim code completion config, it's not needed to
+                  ;; build (or be patched).
+                  (add-before 'patch-source-shebangs 'delete-ycm-file
+                              (lambda _ (delete-file ".ycm_extra_conf.py")))
+                  (replace 'install
+                           (lambda* (#:key outputs #:allow-other-keys)
+                             (let ((bin (string-append
+                                         (assoc-ref outputs "out") "/bin")))
+                               (install-file "notmuch-addrlookup" bin)))))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (inputs
+     `(("glib" ,glib)
+       ("notmuch" ,notmuch)))
+    (home-page "https://github.com/aperezdc/notmuch-addrlookup-c")
+    (synopsis "Address lookup tool for Notmuch")
+    (description "This is an address lookup tool using a Notmuch database,
+useful for email address completion.")
+    (license license:expat)))
+
 (define-public python2-notmuch
   (package
     (name "python2-notmuch")
diff --git a/gnu/packages/mate.scm b/gnu/packages/mate.scm
new file mode 100644
index 0000000000..c4b75f8609
--- /dev/null
+++ b/gnu/packages/mate.scm
@@ -0,0 +1,211 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2016 Fabian Harfert <fhmgufs@web.de>
+;;;
+;;; 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 mate)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (guix packages)
+  #:use-module (guix download)
+  #:use-module (guix utils)
+  #:use-module (guix build-system gnu)
+  #:use-module (gnu packages)
+  #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages glib)
+  #:use-module (gnu packages gtk)
+  #:use-module (gnu packages gnome)
+  #:use-module (gnu packages xorg)
+  #:use-module (gnu packages xdisorg)
+  #:use-module (gnu packages base)
+  #:use-module (gnu packages xml)
+  #:use-module (gnu packages python))
+
+(define-public mate-icon-theme
+  (package
+    (name "mate-icon-theme")
+    (version "1.12.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://pub.mate-desktop.org/releases/"
+                                  (version-major+minor version) "/"
+                                  name "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "0d91rvl9rw3xl8hmdcbb6xvi880kfmh2ra5chhrjimrjqgl57qkp"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("intltool" ,intltool)
+       ("gtk+" ,gtk+)
+       ("icon-naming-utils" ,icon-naming-utils)))
+    (home-page "http://mate-desktop.org/")
+    (synopsis "The MATE desktop environment icon theme")
+    (description
+     "This package contains the default icon theme used by the MATE desktop.")
+    (license license:lgpl3+)))
+
+(define-public mate-themes
+  (package
+    (name "mate-themes")
+    (version "1.12.2")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://pub.mate-desktop.org/releases/"
+                                  (version-major+minor version) "/"
+                                  name "-gtk"
+                                  (version-major+minor (package-version gtk+))
+                                  "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "0kyrlgs5azzj60gnxx2n9qszcligxn959wr42wr0iqnrpiygk5nf"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("intltool" ,intltool)))
+    (inputs
+     `(("gtk+" ,gtk+-2)
+       ("gdk-pixbuf" ,gdk-pixbuf)
+       ("gtk-engines" ,gtk-engines)
+       ("murrine" ,murrine)))
+    (home-page "http://mate-desktop.org/")
+    (synopsis
+     "Official themes for the MATE desktop")
+    (description
+     "This package includes the standard themes for the MATE desktop, for
+example Menta, TraditionalOk, GreenLaguna or BlackMate.")
+    (license (list license:lgpl2.1+ license:cc-by-sa3.0 license:gpl3+
+                   license:gpl2+))))
+
+(define-public mate-desktop
+  (package
+    (name "mate-desktop")
+    (version "1.12.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://pub.mate-desktop.org/releases/"
+                                  (version-major+minor version) "/"
+                                  name "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "00ssrzm07xyrjra075jhir1f8iy382lla7923fhic29lap26mffr"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("intltool" ,intltool)
+       ("glib:bin" ,glib "bin")
+       ("gobject-introspection" ,gobject-introspection)
+       ("yelp-tools" ,yelp-tools)))
+       ;;("gtk-doc" ,gtk-doc))) ; add back in when gtk-doc builds
+    (inputs
+     `(("libxrandr" ,libxrandr)))
+    (propagated-inputs
+     `(("dconf" ,dconf)
+       ("gtk+" ,gtk+-2)
+       ("startup-notification" ,startup-notification)))
+    (home-page "http://mate-desktop.org/")
+    (synopsis "Library with common API for various MATE modules")
+    (description
+     "This package contains a public API shared by several applications on the
+desktop and the mate-about program.")
+    (license (list license:gpl2+ license:lgpl2.0+ license:fdl1.1+))))
+
+(define-public libmateweather
+  (package
+    (name "libmateweather")
+    (version "1.12.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://pub.mate-desktop.org/releases/"
+                                  (version-major+minor version) "/"
+                                  name "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "0qrq6z6knybixnxmsvkw58hm033m91inf523mbvzgv2r822fpakl"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:configure-flags
+       `(,(string-append "--with-zoneinfo-dir="
+                         (assoc-ref %build-inputs "tzdata")
+                         "/share/zoneinfo"))
+       #:phases
+       (modify-phases %standard-phases
+         (add-before
+          'check 'pre-check
+          (lambda* (#:key inputs #:allow-other-keys)
+            (substitute* "data/check-timezones.sh"
+              (("/usr/share/zoneinfo/zone.tab")
+               (string-append (assoc-ref inputs "tzdata")
+                              "/share/zoneinfo/zone.tab")))
+            #t)))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("intltool" ,intltool)
+       ("glib:bin" ,glib "bin")))
+    (inputs
+     `(("dconf" ,dconf)
+       ("tzdata" ,tzdata)))
+    (propagated-inputs
+     `(("gtk+" ,gtk+-2)
+       ("gdk-pixbuf" ,gdk-pixbuf)
+       ("libxml2" ,libxml2)
+       ("libsoup" ,libsoup)))
+    (home-page "http://mate-desktop.org/")
+    (synopsis "MATE library for weather information from the Internet")
+    (description
+     "This library provides acess to weather information from the internet for
+the MATE desktop environment.")
+    (license license:lgpl2.1+)))
+
+(define-public mate-menus
+  (package
+    (name "mate-menus")
+    (version "1.12.0")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://pub.mate-desktop.org/releases/"
+                                  (version-major+minor version) "/"
+                                  name "-" version ".tar.xz"))
+              (sha256
+               (base32
+                "1i4m3fj0vd85zyhqhm8x9yr0h5i08aa4l99zqvbk59ncj6z3bdxh"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after
+          'unpack 'fix-introspection-install-dir
+          (lambda* (#:key outputs #:allow-other-keys)
+            (let ((out (assoc-ref outputs "out")))
+              (substitute* '("configure")
+                (("`\\$PKG_CONFIG --variable=girdir gobject-introspection-1.0`")
+                 (string-append "\"" out "/share/gir-1.0/\""))
+                (("\\$\\(\\$PKG_CONFIG --variable=typelibdir gobject-introspection-1.0\\)")
+                 (string-append out "/lib/girepository-1.0/")))))))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ("intltool" ,intltool)
+       ("gobject-introspection" ,gobject-introspection)))
+    (inputs
+     `(("python" ,python-2)))
+    (propagated-inputs
+     `(("glib" ,glib)))
+    (home-page "http://mate-desktop.org/")
+    (synopsis "Freedesktop menu specification implementation for MATE")
+    (description
+     "The package contains an implementation of the freedesktop menu
+specification, the MATE menu layout configuration files, .directory files and
+assorted menu related utility programs.")
+    (license (list license:gpl2+ license:lgpl2.0+))))
diff --git a/gnu/packages/maths.scm b/gnu/packages/maths.scm
index 51d9cc1ce4..6a9715db73 100644
--- a/gnu/packages/maths.scm
+++ b/gnu/packages/maths.scm
@@ -8,7 +8,7 @@
 ;;; Copyright © 2015 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2015 Fabian Harfert <fhmgufs@web.de>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -177,7 +177,7 @@ numbers.")
 (define-public glpk
   (package
     (name "glpk")
-    (version "4.57")
+    (version "4.58")
     (source
      (origin
       (method url-fetch)
@@ -185,7 +185,7 @@ numbers.")
                           version ".tar.gz"))
       (sha256
        (base32
-        "0p17jj1ixd2m9lnsvx8nywmfmnplfk5gvw25r1gy84qzrjkv48vk"))))
+        "1jmrya04hgwnrxrqqs40i6m9cqka3q601cx3nh9ijyvlg90zlq24"))))
     (build-system gnu-build-system)
     (inputs
      `(("gmp" ,gmp)))
@@ -339,7 +339,7 @@ singular value problems.")
 (define-public gnuplot
   (package
     (name "gnuplot")
-    (version "5.0.1")
+    (version "5.0.2")
     (source
      (origin
       (method url-fetch)
@@ -347,7 +347,7 @@ singular value problems.")
                           version "/gnuplot-" version ".tar.gz"))
       (sha256
        (base32
-        "0irwig94w3f8bn4a444hrjnp7w55vqwv8gqj42jiwn6zf5z5bg3w"))))
+        "146qn414z96c7cc42a1kb9a4kpjc2q2hfdwk44kjjvgmfp9k2ass"))))
     (build-system gnu-build-system)
     (inputs `(("readline" ,readline)
               ("cairo" ,cairo)
diff --git a/gnu/packages/mit-krb5.scm b/gnu/packages/mit-krb5.scm
index 16bef8d97d..5f9868979a 100644
--- a/gnu/packages/mit-krb5.scm
+++ b/gnu/packages/mit-krb5.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2012, 2013 Andreas Enge <andreas@enge.fr>
-;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2015, 2016 Mark H Weaver <mhw@netris.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -21,7 +21,6 @@
   #:use-module (gnu packages)
   #:use-module (gnu packages bison)
   #:use-module (gnu packages perl)
-  #:use-module (gnu packages gcc)
   #:use-module (guix licenses)
   #:use-module (guix packages)
   #:use-module (guix download)
@@ -31,70 +30,31 @@
 (define-public mit-krb5
   (package
     (name "mit-krb5")
-    (version "1.13.2")
+    (version "1.13.3")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://web.mit.edu/kerberos/www/dist/krb5/"
+              (uri (string-append "http://web.mit.edu/kerberos/dist/krb5/"
                                   (version-major+minor version)
-                                  "/krb5-" version "-signed.tar"))
-              (sha256 (base32
-                       "1qbdzyrws7d0q4filsibh28z54pd5l987jr0ygv43iq9085w6a75"))))
+                                  "/krb5-" version ".tar.gz"))
+              (sha256
+               (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")))))
     (build-system gnu-build-system)
     (native-inputs
      `(("bison" ,bison)
-       ("perl" ,perl)
-
-       ;; Include the patches as native-inputs.
-       ,@(map (lambda (label)
-                (let ((input-name (string-append "patch/" label))
-                      (file-name  (string-append name "-" label ".patch")))
-                  `(,input-name ,(search-patch file-name))))
-              '("CVE-2015-2695-pt1"
-                "CVE-2015-2695-pt2"
-                "CVE-2015-2696"
-                "CVE-2015-2697"
-                "CVE-2015-2698-pt1"
-                "CVE-2015-2698-pt2"))))
+       ("perl" ,perl)))
     (arguments
-     `(#:modules ((ice-9 ftw)
-                  (ice-9 match)
-                  (srfi srfi-1)
-                  ,@%gnu-build-system-modules)
-       #:phases
+     `(#:phases
        (modify-phases %standard-phases
-         (replace 'unpack
-           (lambda* (#:key source #:allow-other-keys)
-             (define (sub-directory? name)
-               (and (not (member name '("." "..")))
-                    (equal? (stat:type (stat name))
-                            'directory)))
-             (and (zero? (system* "tar" "xvf" source))
-                  (match (find-files "." "\\.tar\\.gz$")
-                    ((inner-tar-file)
-                     (zero? (system* "tar" "xvf" inner-tar-file))))
-                  (match (scandir "." sub-directory?)
-                    ((directory)
-                     (chdir directory)
-                     #t)))))
-
-         (add-after 'unpack 'apply-patches
-           (lambda* (#:key inputs native-inputs #:allow-other-keys)
-             (let ((patches (filter (match-lambda
-                                      ((name . file)
-                                       (string-prefix? "patch/" name)))
-                                    (or native-inputs inputs))))
-               (every (match-lambda
-                        ((name . file)
-                         (format (current-error-port)
-                                 "applying '~a'...~%" name)
-                         (zero? (system* "patch" "-p1" "--force" "-i" file))))
-                      patches))))
-
-         (add-after 'apply-patches 'enter-source-directory
+         (add-after 'unpack 'enter-source-directory
            (lambda _
              (chdir "src")
              #t))
-
          (add-before 'check 'pre-check
            (lambda* (#:key inputs #:allow-other-keys)
              (let ((perl (assoc-ref inputs "perl")))
diff --git a/gnu/packages/moe.scm b/gnu/packages/moe.scm
index 675ecb6ce2..12929b327a 100644
--- a/gnu/packages/moe.scm
+++ b/gnu/packages/moe.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -27,7 +28,7 @@
 (define-public moe
   (package
     (name "moe")
-    (version "1.7")
+    (version "1.8")
     (source
      (origin
       (method url-fetch)
@@ -35,7 +36,7 @@
                           version ".tar.lz"))
       (sha256
        (base32
-        "1fzimk1qpmsm7wzfnjzzrp4dvdn7ipdb5j7969910g1m93wndfik"))))
+        "0mv4pg38p0dq88xmxxv08rykn7vv4x7gskmdk7nfp3vx37r4xzvy"))))
     (build-system gnu-build-system)
     (native-inputs `(("lzip" ,lzip)))
     (inputs `(("ncurses" ,ncurses)))
diff --git a/gnu/packages/mpd.scm b/gnu/packages/mpd.scm
index b5a0d94a74..5a6377224d 100644
--- a/gnu/packages/mpd.scm
+++ b/gnu/packages/mpd.scm
@@ -4,6 +4,7 @@
 ;;; Copyright © 2014 Cyrill Schenkel <cyrill.schenkel@gmail.com>
 ;;; Copyright © 2014 Ian Denhardt <ian@zenhack.net>
 ;;; Copyright © 2015 Paul van der Walt <paul@denknerd.org>
+;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -69,7 +70,7 @@ interfacing MPD in the C, C++ & Objective C languages.")
 (define-public mpd
   (package
     (name "mpd")
-    (version "0.19.10")
+    (version "0.19.12")
     (source (origin
               (method url-fetch)
               (uri
@@ -78,7 +79,7 @@ interfacing MPD in the C, C++ & Objective C languages.")
                               "/mpd-" version ".tar.xz"))
               (sha256
                (base32
-                "0laqn68iggqf0h06hg282cvpd9wsjqpjfg5fnn9wk3gr48yyp1n3"))))
+                "0xg8w5vn6xd0yfw55qj6wnav7v14nmr00s3d4w5gixbjrv3ycvvv"))))
     (build-system gnu-build-system)
     (inputs `(("ao" ,ao)
               ("alsa-lib" ,alsa-lib)
@@ -178,7 +179,7 @@ terminal using ncurses.")
 (define-public ncmpcpp
   (package
     (name "ncmpcpp")
-    (version "0.6.7")
+    (version "0.7.3")
     (source (origin
               (method url-fetch)
               (uri
@@ -186,13 +187,14 @@ terminal using ncurses.")
                               version ".tar.bz2"))
               (sha256
                (base32
-                "0yr1ib14qkgbsv839anpzkfbwkm6gg8wv4bf98ar7q5l2p2pv008"))))
+                "04mj6r0whikliblxfbz92pibwcd7a3ywkryf01a89zd4bi1jk2rc"))))
     (build-system gnu-build-system)
     (inputs `(("libmpdclient" ,libmpdclient)
               ("boost"  ,boost)
               ("readline" ,readline)
               ("ncurses" ,ncurses)
-              ("taglib" ,taglib)))
+              ("taglib" ,taglib)
+              ("icu4c" ,icu4c)))
     (native-inputs
      `(("pkg-config" ,pkg-config)
        ("automake" ,automake)
@@ -202,12 +204,11 @@ terminal using ncurses.")
      '(#:configure-flags
        '("BOOST_LIB_SUFFIX=" "--with-taglib")
        #:phases
-       (alist-cons-after
-        'unpack 'autogen
-        (lambda _
-          (setenv "NOCONFIGURE" "true")
-          (zero? (system* "sh" "autogen.sh")))
-        %standard-phases)))
+       (modify-phases %standard-phases
+        (add-after 'unpack 'autogen
+         (lambda _
+           (setenv "NOCONFIGURE" "true")
+           (zero? (system* "sh" "autogen.sh")))))))
     (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/music.scm b/gnu/packages/music.scm
index a60ba4bccd..d789cc394f 100644
--- a/gnu/packages/music.scm
+++ b/gnu/packages/music.scm
@@ -2,6 +2,8 @@
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Paul van der Walt <paul@denknerd.org>
+;;; Copyright © 2016 Al McElrath <hello@yrns.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -32,13 +34,15 @@
   #:use-module (gnu packages algebra)
   #:use-module (gnu packages audio)
   #:use-module (gnu packages autotools)
+  #:use-module (gnu packages backup)
   #:use-module (gnu packages base) ;libbdf
-  #:use-module (gnu packages boost)
   #:use-module (gnu packages bison)
+  #:use-module (gnu packages boost)
   #:use-module (gnu packages cdrom)
   #:use-module (gnu packages code)
   #:use-module (gnu packages check)
   #:use-module (gnu packages compression)
+  #:use-module (gnu packages curl)
   #:use-module (gnu packages docbook)
   #:use-module (gnu packages doxygen)
   #:use-module (gnu packages flex)
@@ -46,6 +50,7 @@
   #:use-module (gnu packages fonts)
   #:use-module (gnu packages fontutils)
   #:use-module (gnu packages gcc)
+  #:use-module (gnu packages gnupg)
   #:use-module (gnu packages gettext)
   #:use-module (gnu packages ghostscript)
   #:use-module (gnu packages gl)
@@ -145,64 +150,32 @@ many input formats and provides a customisable Vi-style user interface.")
 (define-public hydrogen
   (package
     (name "hydrogen")
-    (version "0.9.5.1")
+    (version "0.9.6.1")
     (source (origin
               (method url-fetch)
               (uri (string-append
-                    "mirror://sourceforge/hydrogen/Hydrogen/"
-                    (version-prefix version 3) "%20Sources/"
-                    "hydrogen-" version ".tar.gz"))
+                    "https://github.com/hydrogen-music/hydrogen/archive/"
+                    version ".tar.gz"))
               (sha256
                (base32
-                "1fvyp6gfzcqcc90dmaqbm11p272zczz5pfz1z4lj33nfr7z0bqgb"))))
-    (build-system gnu-build-system)
+                "0vxnaqfmcv7hhk0cj67imdcqngspnck7f0wfmvhfgfqa7x1xznll"))))
+    (build-system cmake-build-system)
     (arguments
-     `(#:tests? #f ;no "check" target
-       #: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, "))))
-         (replace 'build
-                  (lambda* (#:key inputs outputs #:allow-other-keys)
-                    (let ((out (assoc-ref outputs "out")))
-                      (zero? (system* "scons"
-                                      (string-append "prefix=" out)
-                                      "lrdf=0" ; cannot be found
-                                      "lash=1")))))
-         (add-before
-          'install
-          'fix-img-install
-          (lambda _
-            ;; The whole ./data/img directory is copied to the target first.
-            ;; Scons complains about existing files when we try to install all
-            ;; images a second time.
-            (substitute* "Sconstruct"
-              (("os.path.walk\\(\"./data/img/\",install_images,env\\)") ""))
-            #t))
-         (replace 'install (lambda _ (zero? (system* "scons" "install")))))))
+    `(#:test-target "tests"))
     (native-inputs
-     `(("scons" ,scons)
-       ("python" ,python-2)
+     `(("cppunit" ,cppunit)
        ("pkg-config" ,pkg-config)))
     (inputs
-     `(("zlib" ,zlib)
-       ("libtar" ,libtar)
-       ("alsa-lib" ,alsa-lib)
+     `(("alsa-lib" ,alsa-lib)
        ("jack" ,jack-1)
+       ;; ("ladspa" ,ladspa) ; cannot find during configure
        ("lash" ,lash)
-       ;;("lrdf" ,lrdf) ;FIXME: cannot be found by scons
+       ("libarchive" ,libarchive)
+       ("libsndfile" ,libsndfile)
+       ("libtar" ,libtar)
+       ("lrdf" ,lrdf)
        ("qt" ,qt-4)
-       ("libsndfile" ,libsndfile)))
+       ("zlib" ,zlib)))
     (home-page "http://www.hydrogen-music.org")
     (synopsis "Drum machine")
     (description
@@ -252,6 +225,54 @@ enable professional yet simple and intuitive pattern-based drum programming.")
 you to define complex tempo maps for entire songs or performances.")
     (license license:gpl2+)))
 
+(define-public gtklick
+  (package
+    (name "gtklick")
+    (version "0.6.4")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://das.nasophon.de/download/gtklick-"
+                                  version ".tar.gz"))
+              (sha256
+               (base32
+                "0dq1km6njnzsqdqyf6wzir9g733z0mc9vmxfg2383k3c2a2di6bp"))))
+    (build-system python-build-system)
+    (arguments
+     `(#:tests? #f ; no tests
+       #:python ,python-2
+       #:phases
+       (modify-phases %standard-phases
+         (add-before 'build 'add-sitedirs
+           ;; .pth files are not automatically interpreted unless the
+           ;; directories containing them are added as "sites".  The directories
+           ;; are then added to those in the PYTHONPATH.  This is required for
+           ;; the operation of pygtk.
+           (lambda _
+             (substitute* "gtklick/gtklick.py"
+               (("import pygtk")
+                "import pygtk, site, sys
+for path in [path for path in sys.path if 'site-packages' in path]: site.addsitedir(path)"))))
+         (add-after 'unpack 'inject-store-path-to-klick
+           (lambda* (#:key inputs #:allow-other-keys)
+             (substitute* "gtklick/klick_backend.py"
+               (("KLICK_PATH = 'klick'")
+                (string-append "KLICK_PATH = '"
+                               (assoc-ref inputs "klick")
+                               "/bin/klick'")))
+             #t)))))
+    (inputs
+     `(("klick" ,klick)
+       ("python2-pyliblo" ,python2-pyliblo)
+       ("python2-pygtk" ,python2-pygtk)))
+    (native-inputs
+     `(("gettext" ,gnu-gettext)))
+    (home-page "http://das.nasophon.de/gtklick/")
+    (synopsis "Simple metronome with an easy-to-use graphical interface")
+    (description
+     "Gtklick is a simple metronome with an easy-to-use graphical user
+interface.  It is implemented as a frontend to @code{klick}.")
+    (license license:gpl2+)))
+
 (define-public lilypond
   (package
     (name "lilypond")
@@ -916,15 +937,15 @@ instrument or MIDI file player.")
 (define-public zynaddsubfx
   (package
     (name "zynaddsubfx")
-    (version "2.5.2")
+    (version "2.5.3")
     (source (origin
               (method url-fetch)
               (uri (string-append
                     "mirror://sourceforge/zynaddsubfx/zynaddsubfx/"
-                    version "/zynaddsubfx-" version ".tar.gz"))
+                    version "/zynaddsubfx-" version ".tar.bz2"))
               (sha256
                (base32
-                "11yrady7xwfrzszkk2fvq81ymv99mq474h60qnirk27khdygk24m"))))
+                "04da54p19p7f5wm6vm7abbjbsil1qf7n5f4adj01jm6b0wqigvgb"))))
     (build-system cmake-build-system)
     (arguments
      `(#:phases
@@ -1078,3 +1099,38 @@ computer's keyboard.")
 JACK for audio and ALSA sequencer for MIDI as multimedia infrastructures and
 follows a traditional multi-track tape recorder control paradigm.")
     (license license:gpl2+)))
+
+(define-public pianobar
+  (package
+    (name "pianobar")
+    (version "2015.11.22")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "https://github.com/PromyLOPh/"
+                                  name "/archive/" version ".tar.gz"))
+              (file-name (string-append name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "022df19bhxqvkhy0qy21xahba5s1fm17b13y0p9p9dnf2yl44wfv"))))
+    (build-system gnu-build-system)
+    (arguments
+     `(#:tests? #f ; no tests
+       #:make-flags (list "CC=gcc" "CFLAGS=-std=c99"
+                          (string-append "PREFIX=" %output))
+       #:phases (modify-phases %standard-phases
+                  (delete 'configure))))
+    (inputs
+     `(("ao" ,ao)
+       ("curl" ,curl)
+       ("libgcrypt" ,libgcrypt)
+       ("json-c" ,json-c)
+       ("ffmpeg" ,ffmpeg)))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (home-page "http://6xq.net/projects/pianobar/")
+    (synopsis "Console-based pandora.com player")
+    (description "pianobar is a console-based music player for the
+personalized online radio pandora.com.  It has configurable keys for playing
+and managing stations, can be controlled remotely via fifo, and can run
+event-based scripts for scrobbling, notifications, etc.")
+    (license license:expat)))
diff --git a/gnu/packages/nano.scm b/gnu/packages/nano.scm
index 352e2b47e0..a1f7019c0d 100644
--- a/gnu/packages/nano.scm
+++ b/gnu/packages/nano.scm
@@ -28,7 +28,7 @@
 (define-public nano
   (package
     (name "nano")
-    (version "2.5.1")
+    (version "2.5.2")
     (source
      (origin
       (method url-fetch)
@@ -36,7 +36,7 @@
                           version ".tar.gz"))
       (sha256
        (base32
-        "1piv8prj6w3rvsrrx41ra8c10b8fzkgjhnm6399lsgqqpw0wlvz0"))))
+        "0hgbmqzjy1pashb1g3qby75pqb7r5g9bmn1iajlx50082b2nmgc9"))))
     (build-system gnu-build-system)
     (inputs
      `(("gettext" ,gnu-gettext)
diff --git a/gnu/packages/nettle.scm b/gnu/packages/nettle.scm
index b20ddfad26..d1203dfe75 100644
--- a/gnu/packages/nettle.scm
+++ b/gnu/packages/nettle.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Mark H Weaver <mhw@netris.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -59,30 +60,17 @@ themselves.")
   ;; This version is not API-compatible with version 2.  In particular, lsh
   ;; cannot use it yet.  So keep it separate.
   (package (inherit nettle-2)
-    (version "3.1.1")
+    (version "3.2")
     (source (origin
               (method url-fetch)
               (uri (string-append "mirror://gnu/nettle/nettle-"
                                   version ".tar.gz"))
               (sha256
                (base32
-                "0k1x57zviysvi91lkk66cg8v819vywm5g5yqs22wppfqcifx5m2z"))))
+                "15wxhk52yc62rx0pddmry66hqm6z5brrrkx4npd3wh9nybg86hpa"))))
     (arguments
-     `(#:phases
-       (modify-phases %standard-phases
-         (add-after
-          'configure 'disable-ifunc-init-method
-          (lambda _
-            ;; Work around problems with the ifunc initialization method in
-            ;; nettle.  For details, see
-            ;; <http://lists.lysator.liu.se/pipermail/nettle-bugs/2015/003389.html>
-            ;; and <https://sourceware.org/ml/libc-help/2015-06/msg00010.html>.
-            (substitute* "config.h"
-              (("#define HAVE_LINK_IFUNC 1")
-               "/* #undef HAVE_LINK_IFUNC */"))
-            #t)))
-       ,@(substitute-keyword-arguments (package-arguments nettle-2)
-           ((#:configure-flags flags)
-            ;; Build "fat" binaries where the right implementation is chosen
-            ;; at run time based on CPU features (starting from 3.1.)
-            `(cons "--enable-fat" ,flags)))))))
+     (substitute-keyword-arguments (package-arguments nettle-2)
+       ((#:configure-flags flags)
+        ;; Build "fat" binaries where the right implementation is chosen
+        ;; at run time based on CPU features (starting from 3.1.)
+        `(cons "--enable-fat" ,flags))))))
diff --git a/gnu/packages/ocaml.scm b/gnu/packages/ocaml.scm
index 1311b1bc37..4b5ac617d5 100644
--- a/gnu/packages/ocaml.scm
+++ b/gnu/packages/ocaml.scm
@@ -4,6 +4,7 @@
 ;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015 David Hashe <david.hashe@dhashe.com>
 ;;; Copyright © 2016 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -42,6 +43,7 @@
   #:use-module (gnu packages lynx)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages python)
+  #:use-module (gnu packages m4)
   #:use-module (gnu packages ncurses)
   #:use-module (gnu packages version-control)
   #:use-module (gnu packages curl))
@@ -60,6 +62,10 @@
                (base32
                 "1qwwvy8nzd87hk8rd9sm667nppakiapnx4ypdwcrlnav2dz6kil3"))))
     (build-system gnu-build-system)
+    (native-search-paths
+     (list (search-path-specification
+            (variable "OCAMLPATH")
+            (files (list (string-append "lib/ocaml"))))))
     (native-inputs
      `(("perl" ,perl)
        ("pkg-config" ,pkg-config)))
@@ -471,6 +477,8 @@ provers.")
     (arguments
      `(#:tests? #f ; no check target
 
+       ;; opt: also install cmxa files
+       #:make-flags (list "all" "opt")
        ;; Occasionally we would get "Error: Unbound module GtkThread" when
        ;; compiling 'gtkThInit.ml', with 'make -j'.  So build sequentially.
        #:parallel-build? #f
@@ -613,3 +621,52 @@ a collection of files and directories to be stored on different hosts
 brought up to date by propagating the changes in each replica
 to the other.")
     (license gpl3+)))
+
+(define-public ocaml-findlib
+  (package
+    (name "ocaml-findlib")
+    (version "1.6.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://download.camlcity.org/download/"
+                                  "findlib" "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "02abg1lsnwvjg3igdyb8qjgr5kv1nbwl4gaf8mdinzfii5p82721"))
+              (patches
+               (list (search-patch "ocaml-findlib-make-install.patch")))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("camlp4" ,camlp4)
+       ("m4" ,m4)
+       ("ocaml" ,ocaml)))
+    (arguments
+     `(#:tests? #f  ; no test suite
+       #:parallel-build? #f
+       #:make-flags (list "all" "opt")
+       #:phases (modify-phases %standard-phases
+                  (replace
+                   'configure
+                   (lambda* (#:key inputs outputs #:allow-other-keys)
+                     (let ((out (assoc-ref outputs "out")))
+                       (system*
+                        "./configure"
+                        "-bindir" (string-append out "/bin")
+                        "-config" (string-append out "/etc/ocamfind.conf")
+                        "-mandir" (string-append out "/share/man")
+                        "-sitelib" (string-append out "/lib/ocaml/site-lib")
+                        "-with-toolbox")))))))
+    (home-page "http://projects.camlcity.org/projects/findlib.html")
+    (synopsis "Management tool for OCaml libraries")
+    (description
+     "The \"findlib\" library provides a scheme to manage reusable software
+components (packages), and includes tools that support this scheme.  Packages
+are collections of OCaml modules for which metainformation can be stored.  The
+packages are kept in the filesystem hierarchy, but with strict directory
+structure.  The library contains functions to look the directory up that
+stores a package, to query metainformation about a package, and to retrieve
+dependency information about multiple packages.  There is also a tool that
+allows the user to enter queries on the command-line.  In order to simplify
+compilation and linkage, there are new frontends of the various OCaml
+compilers that can directly deal with packages.")
+    (license x11)))
diff --git a/gnu/packages/openbox.scm b/gnu/packages/openbox.scm
index 9dd756d9f3..3135756e7b 100644
--- a/gnu/packages/openbox.scm
+++ b/gnu/packages/openbox.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 Julien Lepiller <julien@lepiller.eu>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -31,15 +32,15 @@
 (define-public openbox
   (package
     (name "openbox")
-    (version "3.5.2")
+    (version "3.6.1")
     (source (origin
               (method url-fetch)
               (uri (string-append
                     "http://www.icculus.org/openbox/releases/" name "-"
-                    version ".tar.gz"))
+                    version ".tar.xz"))
               (sha256
                (base32
-                "0cxgb334zj6aszwiki9g10i56sm18i7w1kw52vdnwgzq27pv93qj"))))
+                "0vg2y1qddsdxkjv806mzpvmkgzliab8ll4s7zm7ma5jnriamirxb"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)))
     (inputs `(("imlib2" ,imlib2)
diff --git a/gnu/packages/openstack.scm b/gnu/packages/openstack.scm
index e258b89e2f..0fa488f842 100644
--- a/gnu/packages/openstack.scm
+++ b/gnu/packages/openstack.scm
@@ -304,12 +304,7 @@ portions of your testing code.")
     (license asl2.0)))
 
 (define-public python2-requests-mock
-  (let ((requests-mock (package-with-python2 python-requests-mock)))
-    (package (inherit requests-mock)
-      (propagated-inputs
-       `(("python2-requests" ,python2-requests)
-         ,@(alist-delete "python-requests"
-                         (package-propagated-inputs requests-mock)))))))
+  (package-with-python2 python-requests-mock))
 
 (define-public python-stevedore
   (package
@@ -392,12 +387,7 @@ common features used in Tempest.")
     (license asl2.0)))
 
 (define-public python2-tempest-lib
-  (let ((tempest-lib (package-with-python2 python-tempest-lib)))
-    (package (inherit tempest-lib)
-      (propagated-inputs
-       `(("python2-jsonschema", python2-jsonschema)
-         ,@(alist-delete "python-jsonschema"
-                         (package-propagated-inputs tempest-lib)))))))
+  (package-with-python2 python-tempest-lib))
 
 ;; Packages from the Oslo library
 (define-public python-oslo.config
@@ -606,9 +596,7 @@ from the OpenStack project.")
     (license asl2.0)))
 
 (define-public python2-oslosphinx
-  (let ((oslosphinx (package-with-python2 python-oslosphinx)))
-    (package (inherit oslosphinx)
-      (propagated-inputs `(("python2-requests" ,python2-requests))))))
+  (package-with-python2 python-oslosphinx))
 
 (define-public python-oslotest
   (package
@@ -782,7 +770,7 @@ LDAP.")
           "1j33l4z9vqh0scfncl4fxg01zr1hgqxhhai6gvcih1gccqm4nd7p"))))
     (build-system python-build-system)
     (native-inputs
-     `(("python-pbr", python-pbr)
+     `(("python-pbr" ,python-pbr)
        ("python-setuptools" ,python-setuptools)
        ("python-sphinx" ,python-sphinx)
        ;; The folloing packages are needed for the tests.
diff --git a/gnu/packages/owncloud.scm b/gnu/packages/owncloud.scm
index 084a0a2863..e75426e579 100644
--- a/gnu/packages/owncloud.scm
+++ b/gnu/packages/owncloud.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -34,14 +34,14 @@
 (define-public owncloud-client
   (package
     (name "owncloud-client")
-    (version "2.1.0")
+    (version "2.1.1")
     (source
      (origin
        (method url-fetch)
        (uri (string-append "https://download.owncloud.com/desktop/stable/"
                            "owncloudclient-" version ".tar.xz"))
        (sha256
-        (base32 "0gyhll4yfxcpyc5m73zar5f33qgnmpwiggw2adxdiqy55hc3ymbk"))))
+        (base32 "1jxi439qff4acvyvszjprj42kvzhlz255wv8g4p3jrf55svzwz2f"))))
     (build-system cmake-build-system)
     (arguments
      `(#:phases
diff --git a/gnu/packages/package-management.scm b/gnu/packages/package-management.scm
index c7494c1b8d..ac6d84813f 100644
--- a/gnu/packages/package-management.scm
+++ b/gnu/packages/package-management.scm
@@ -239,14 +239,14 @@ the Nix package manager.")
 (define-public nix
   (package
     (name "nix")
-    (version "1.10")
+    (version "1.11.2")
     (source (origin
              (method url-fetch)
              (uri (string-append "http://nixos.org/releases/nix/nix-"
                                  version "/nix-" version ".tar.xz"))
              (sha256
               (base32
-               "1xhh7l1dqwn6i3m51xp8l0aa95da3823w4h8n8hfxlcxaixcl4jn"))))
+               "1mk9z75gklxcv6kzwwz1h5r2ci5kjy6bh7qwk4m5lf5v9s0k64pw"))))
     (build-system gnu-build-system)
     ;; XXX: Should we pass '--with-store-dir=/gnu/store'?  But then we'd also
     ;; need '--localstatedir=/var'.  But then!  The thing would use /var/nix
@@ -389,21 +389,23 @@ transactions from C or Python.")
 (define-public diffoscope
   (package
     (name "diffoscope")
-    (version "34")
+    (version "49")
     (source (origin
-              (method git-fetch)
-              (uri (git-reference
-                    (url
-                     "https://anonscm.debian.org/cgit/reproducible/diffoscope.git")
-                    (commit version)))
+              (method url-fetch)
+              (uri (pypi-uri name version))
               (sha256
                (base32
-                "1g8b7bpkmns0355gkr3a244affwx4xzqwahwsl6ivw4z0qv7dih8"))
-              (file-name (string-append name "-" version "-checkout"))))
+                "1mf6b7j82ckn90ggz6bp6c2jydz87xj8r8jmfl4hg7jcmf7dxmim"))))
     (build-system python-build-system)
     (arguments
-     `(#:python ,python-2
-       #:phases (modify-phases %standard-phases
+     `(#:phases (modify-phases %standard-phases
+                  ;; setup.py mistakenly requires python-magic from PyPi, even
+                  ;; though the Python bindings of `file` are sufficient.
+                  ;; https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=815844
+                  (add-after 'unpack 'dependency-on-python-magic
+                    (lambda _
+                      (substitute* "setup.py"
+                        (("'python-magic',") ""))))
                   (add-before 'build 'disable-egg-zipping
                     (lambda _
                       ;; Leave the .egg file uncompressed.
@@ -411,27 +413,16 @@ transactions from C or Python.")
                         (display "\n[easy_install]\nzip_ok = 0\n"
                                  port)
                         (close-port port)
-                        #t)))
-                  (add-before 'build 'dependency-on-rpm
-                    (lambda _
-                      (substitute* "setup.py"
-                        ;; Somehow this requirement is reported as not met,
-                        ;; even though rpm.py is in the search path.  So
-                        ;; delete it.
-                        (("'rpm-python',") ""))
-                      #t)))
-       ;; FIXME: Some obscure test failures.
-       #:tests? #f))
+                        #t))))))
     (inputs `(("rpm" ,rpm)                        ;for rpm-python
-              ("python-file" ,python2-file)
-              ("python-debian" ,python2-debian)
-              ("python-libarchive-c" ,python2-libarchive-c)
-              ("python-tlsh" ,python2-tlsh)
+              ("python-file" ,python-file)
+              ("python-debian" ,python-debian)
+              ("python-libarchive-c" ,python-libarchive-c)
+              ("python-tlsh" ,python-tlsh)
 
               ;; Below are modules used for tests.
-              ("python-pytest" ,python2-pytest)
-              ("python-chardet" ,python2-chardet)))
-    (native-inputs `(("python-setuptools" ,python2-setuptools)))
+              ("python-pytest" ,python-pytest)
+              ("python-chardet" ,python-chardet)))
     (home-page "http://diffoscope.org/")
     (synopsis "Compare files, archives, and directories in depth")
     (description
diff --git a/gnu/packages/parallel.scm b/gnu/packages/parallel.scm
index 8f63bda25c..e336afb40d 100644
--- a/gnu/packages/parallel.scm
+++ b/gnu/packages/parallel.scm
@@ -1,7 +1,9 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013,2014 Eric Bavier <bavier@member.fsf.org>
+;;; Copyright © 2013, 2014 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Pjotr Prins <pjotr.guix@thebird.nl>
+;;; Copyright © 2016 Andreas Enge <andreas@enge.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -19,17 +21,28 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu packages parallel)
-  #:use-module (guix packages)
-  #:use-module (guix licenses)
-  #:use-module (guix download)
   #:use-module (guix build-system gnu)
+  #:use-module (guix download)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (guix packages)
   #:use-module (gnu packages)
-  #:use-module (gnu packages perl))
+  #:use-module (gnu packages admin)
+  #:use-module (gnu packages autotools)
+  #:use-module (gnu packages freeipmi)
+  #:use-module (gnu packages linux)
+  #:use-module (gnu packages mpi)
+  #:use-module (gnu packages perl)
+  #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages python)
+  #:use-module (gnu packages readline)
+  #:use-module (gnu packages tcl)
+  #:use-module (gnu packages tls)
+  #:use-module (gnu packages web))
 
 (define-public parallel
   (package
     (name "parallel")
-    (version "20151222")
+    (version "20160122")
     (source
      (origin
       (method url-fetch)
@@ -37,7 +50,7 @@
                           version ".tar.bz2"))
       (sha256
        (base32
-        "03czpnsj77xxzqxzzr1b39ym9acn94hknzbilbh28v5q1wk7r4mf"))))
+        "1xs8y8jh7wyjs27079xz0ja7xfi4dywz8d6hbkl44mafdnnfjfiy"))))
     (build-system gnu-build-system)
     (inputs `(("perl" ,perl)))
     (home-page "http://www.gnu.org/software/parallel/")
@@ -46,4 +59,65 @@
      "GNU Parallel is a tool for executing shell jobs in parallel using one
 or more computers.  Jobs can consist of single commands or of scripts
 and they are executed on lists of files, hosts, users or other items.")
-    (license gpl3+)))
+    (license license:gpl3+)))
+
+(define-public slurm
+  (package
+   (name "slurm")
+   (version "15.08.7.1")
+   (source (origin
+            (method url-fetch)
+            (uri (string-append
+                  "https://github.com/SchedMD/slurm/archive/slurm-"
+                  (string-join (string-split version #\.) "-") ".tar.gz"))
+            (file-name (string-append name "-" version ".tar.gz"))
+            (sha256
+             (base32
+              "1rmi35l4img00dr4vic8cv8s7b6n1yx1mkq2s7kjf5hvqdh6s2ki"))
+            (patches (list
+             (search-patch "slurm-configure-remove-nonfree-contribs.patch")))
+            (modules '((guix build utils)))
+            (snippet
+             '(begin
+                (delete-file-recursively "contribs")
+                #t))))
+   ;; FIXME: More optional inputs could be added,
+   ;; in particular mysql and gtk+.
+   (inputs `(("expect" ,expect)
+             ("freeipmi" ,freeipmi)
+             ("hwloc" ,hwloc)
+             ("json-c" ,json-c)
+             ("linux-pam" , linux-pam)
+             ("munge" ,munge)
+             ("numactl" ,numactl)
+             ("openssl" ,openssl)
+             ("perl" ,perl)
+             ("python" ,python-wrapper)
+             ("readline" ,readline)))
+   (native-inputs
+    `(("autoconf" ,autoconf)
+      ("pkg-config" ,pkg-config)))
+   (build-system gnu-build-system)
+   (arguments
+    `(#:configure-flags
+      (list "--enable-pam"
+            (string-append "--with-freeipmi=" (assoc-ref %build-inputs "freeipmi"))
+            (string-append "--with-hwloc=" (assoc-ref %build-inputs "hwloc"))
+            (string-append "--with-json=" (assoc-ref %build-inputs "json-c"))
+            (string-append "--with-munge=" (assoc-ref %build-inputs "munge"))
+            (string-append "--with-ssl=" (assoc-ref %build-inputs "openssl")))
+      #:phases
+      (modify-phases %standard-phases
+       (add-before
+        'configure 'autogen
+        (lambda _ (zero? (system* "autoconf"))))))) ; configure.ac was patched
+   (home-page "http://slurm.schedmd.com/")
+   (synopsis "Workload manager for cluster computing")
+   (description
+    "SLURM is a fault-tolerant and highly scalable cluster management and job
+scheduling system for large and small clusters.  It allocates access to
+resources (computer nodes) to users for some duration of time, provides a
+framework for starting, executing, and monitoring work (typically a parallel
+job) on a set of allocated nodes, and arbitrates contention for resources
+by managing a queue of pending work.")
+   (license license:gpl2+)))
diff --git a/gnu/packages/patches/cpio-CVE-2016-2037.patch b/gnu/packages/patches/cpio-CVE-2016-2037.patch
new file mode 100644
index 0000000000..f1e068fb45
--- /dev/null
+++ b/gnu/packages/patches/cpio-CVE-2016-2037.patch
@@ -0,0 +1,49 @@
+Fix CVE-2016-2037 (out of bounds write in process_copy_in()).
+
+Copied from upstream mailing list:
+https://lists.gnu.org/archive/html/bug-cpio/2016-01/msg00005.html
+
+---
+
+ Other calls to cpio_safer_name_suffix seem to be safe.
+ .
+ * src/copyin.c (process_copy_in):  Make sure that file_hdr.c_name
+ has at least two bytes allocated.
+ * src/util.c (cpio_safer_name_suffix): Document that use of this
+ function requires to be careful.
+Author: Pavel Raiskup <praiskup@redhat.com>
+
+---
+ src/copyin.c | 2 ++
+ src/util.c   | 5 ++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+Index: cpio-2.11+dfsg/src/copyin.c
+===================================================================
+--- cpio-2.11+dfsg.orig/src/copyin.c
++++ cpio-2.11+dfsg/src/copyin.c
+@@ -1433,6 +1433,8 @@ process_copy_in ()
+ 	  break;
+ 	}
+ 
++      if (file_hdr.c_namesize <= 1)
++        file_hdr.c_name = xrealloc(file_hdr.c_name, 2);
+       cpio_safer_name_suffix (file_hdr.c_name, false, !no_abs_paths_flag,
+ 			      false);
+       
+Index: cpio-2.11+dfsg/src/util.c
+===================================================================
+--- cpio-2.11+dfsg.orig/src/util.c
++++ cpio-2.11+dfsg/src/util.c
+@@ -1374,7 +1374,10 @@ set_file_times (int fd,
+ }
+ 
+ /* Do we have to ignore absolute paths, and if so, does the filename
+-   have an absolute path?  */
++   have an absolute path?
++   Before calling this function make sure that the allocated NAME buffer has
++   capacity at least 2 bytes to allow us to store the "." string inside.  */
++
+ void
+ cpio_safer_name_suffix (char *name, bool link_target, bool absolute_names,
+ 			bool strip_leading_dots)
diff --git a/gnu/packages/patches/glibc-CVE-2015-7547.patch b/gnu/packages/patches/glibc-CVE-2015-7547.patch
new file mode 100644
index 0000000000..9a0909af74
--- /dev/null
+++ b/gnu/packages/patches/glibc-CVE-2015-7547.patch
@@ -0,0 +1,559 @@
+Copied from Fedora:
+http://pkgs.fedoraproject.org/cgit/rpms/glibc.git/tree/glibc-CVE-2015-7547.patch?h=f23&id=9f1734eb6ce3257b788d6e9203572e8204c6c584
+
+Adapted to apply cleanly to glibc-2.22.
+
+Index: b/resolv/nss_dns/dns-host.c
+===================================================================
+--- a/resolv/nss_dns/dns-host.c
++++ b/resolv/nss_dns/dns-host.c
+@@ -1031,7 +1031,10 @@ gaih_getanswer_slice (const querybuf *an
+   int h_namelen = 0;
+ 
+   if (ancount == 0)
+-    return NSS_STATUS_NOTFOUND;
++    {
++      *h_errnop = HOST_NOT_FOUND;
++      return NSS_STATUS_NOTFOUND;
++    }
+ 
+   while (ancount-- > 0 && cp < end_of_message && had_error == 0)
+     {
+@@ -1208,7 +1211,14 @@ gaih_getanswer_slice (const querybuf *an
+   /* Special case here: if the resolver sent a result but it only
+      contains a CNAME while we are looking for a T_A or T_AAAA record,
+      we fail with NOTFOUND instead of TRYAGAIN.  */
+-  return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
++  if (canon != NULL)
++    {
++      *h_errnop = HOST_NOT_FOUND;
++      return NSS_STATUS_NOTFOUND;
++    }
++
++  *h_errnop = NETDB_INTERNAL;
++  return NSS_STATUS_TRYAGAIN;
+ }
+ 
+ 
+@@ -1222,11 +1232,101 @@ gaih_getanswer (const querybuf *answer1,
+ 
+   enum nss_status status = NSS_STATUS_NOTFOUND;
+ 
++  /* Combining the NSS status of two distinct queries requires some
++     compromise and attention to symmetry (A or AAAA queries can be
++     returned in any order).  What follows is a breakdown of how this
++     code is expected to work and why. We discuss only SUCCESS,
++     TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
++     that apply (though RETURN and MERGE exist).  We make a distinction
++     between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
++     A recoverable TRYAGAIN is almost always due to buffer size issues
++     and returns ERANGE in errno and the caller is expected to retry
++     with a larger buffer.
++
++     Lastly, you may be tempted to make significant changes to the
++     conditions in this code to bring about symmetry between responses.
++     Please don't change anything without due consideration for
++     expected application behaviour.  Some of the synthesized responses
++     aren't very well thought out and sometimes appear to imply that
++     IPv4 responses are always answer 1, and IPv6 responses are always
++     answer 2, but that's not true (see the implemetnation of send_dg
++     and send_vc to see response can arrive in any order, particlarly
++     for UDP). However, we expect it holds roughly enough of the time
++     that this code works, but certainly needs to be fixed to make this
++     a more robust implementation.
++
++     ----------------------------------------------
++     | Answer 1 Status /   | Synthesized | Reason |
++     | Answer 2 Status     | Status      |        |
++     |--------------------------------------------|
++     | SUCCESS/SUCCESS     | SUCCESS     | [1]    |
++     | SUCCESS/TRYAGAIN    | TRYAGAIN    | [5]    |
++     | SUCCESS/TRYAGAIN'   | SUCCESS     | [1]    |
++     | SUCCESS/NOTFOUND    | SUCCESS     | [1]    |
++     | SUCCESS/UNAVAIL     | SUCCESS     | [1]    |
++     | TRYAGAIN/SUCCESS    | TRYAGAIN    | [2]    |
++     | TRYAGAIN/TRYAGAIN   | TRYAGAIN    | [2]    |
++     | TRYAGAIN/TRYAGAIN'  | TRYAGAIN    | [2]    |
++     | TRYAGAIN/NOTFOUND   | TRYAGAIN    | [2]    |
++     | TRYAGAIN/UNAVAIL    | TRYAGAIN    | [2]    |
++     | TRYAGAIN'/SUCCESS   | SUCCESS     | [3]    |
++     | TRYAGAIN'/TRYAGAIN  | TRYAGAIN    | [3]    |
++     | TRYAGAIN'/TRYAGAIN' | TRYAGAIN'   | [3]    |
++     | TRYAGAIN'/NOTFOUND  | TRYAGAIN'   | [3]    |
++     | TRYAGAIN'/UNAVAIL   | UNAVAIL     | [3]    |
++     | NOTFOUND/SUCCESS    | SUCCESS     | [3]    |
++     | NOTFOUND/TRYAGAIN   | TRYAGAIN    | [3]    |
++     | NOTFOUND/TRYAGAIN'  | TRYAGAIN'   | [3]    |
++     | NOTFOUND/NOTFOUND   | NOTFOUND    | [3]    |
++     | NOTFOUND/UNAVAIL    | UNAVAIL     | [3]    |
++     | UNAVAIL/SUCCESS     | UNAVAIL     | [4]    |
++     | UNAVAIL/TRYAGAIN    | UNAVAIL     | [4]    |
++     | UNAVAIL/TRYAGAIN'   | UNAVAIL     | [4]    |
++     | UNAVAIL/NOTFOUND    | UNAVAIL     | [4]    |
++     | UNAVAIL/UNAVAIL     | UNAVAIL     | [4]    |
++     ----------------------------------------------
++
++     [1] If the first response is a success we return success.
++         This ignores the state of the second answer and in fact
++         incorrectly sets errno and h_errno to that of the second
++	 answer.  However because the response is a success we ignore
++	 *errnop and *h_errnop (though that means you touched errno on
++         success).  We are being conservative here and returning the
++         likely IPv4 response in the first answer as a success.
++
++     [2] If the first response is a recoverable TRYAGAIN we return
++	 that instead of looking at the second response.  The
++	 expectation here is that we have failed to get an IPv4 response
++	 and should retry both queries.
++
++     [3] If the first response was not a SUCCESS and the second
++	 response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
++	 or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
++	 result from the second response, otherwise the first responses
++	 status is used.  Again we have some odd side-effects when the
++	 second response is NOTFOUND because we overwrite *errnop and
++	 *h_errnop that means that a first answer of NOTFOUND might see
++	 its *errnop and *h_errnop values altered.  Whether it matters
++	 in practice that a first response NOTFOUND has the wrong
++	 *errnop and *h_errnop is undecided.
++
++     [4] If the first response is UNAVAIL we return that instead of
++	 looking at the second response.  The expectation here is that
++	 it will have failed similarly e.g. configuration failure.
++
++     [5] Testing this code is complicated by the fact that truncated
++	 second response buffers might be returned as SUCCESS if the
++	 first answer is a SUCCESS.  To fix this we add symmetry to
++	 TRYAGAIN with the second response.  If the second response
++	 is a recoverable error we now return TRYAGIN even if the first
++	 response was SUCCESS.  */
++
+   if (anslen1 > 0)
+     status = gaih_getanswer_slice(answer1, anslen1, qname,
+ 				  &pat, &buffer, &buflen,
+ 				  errnop, h_errnop, ttlp,
+ 				  &first);
++
+   if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
+        || (status == NSS_STATUS_TRYAGAIN
+ 	   /* We want to look at the second answer in case of an
+@@ -1242,8 +1342,15 @@ gaih_getanswer (const querybuf *answer1,
+ 						     &pat, &buffer, &buflen,
+ 						     errnop, h_errnop, ttlp,
+ 						     &first);
++      /* Use the second response status in some cases.  */
+       if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
+ 	status = status2;
++      /* Do not return a truncated second response (unless it was
++         unavoidable e.g. unrecoverable TRYAGAIN).  */
++      if (status == NSS_STATUS_SUCCESS
++	  && (status2 == NSS_STATUS_TRYAGAIN
++	      && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
++	status = NSS_STATUS_TRYAGAIN;
+     }
+ 
+   return status;
+Index: b/resolv/res_query.c
+===================================================================
+--- a/resolv/res_query.c
++++ b/resolv/res_query.c
+@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
+ 		  {
+ 		    free (*answerp2);
+ 		    *answerp2 = NULL;
++		    *nanswerp2 = 0;
+ 		    *answerp2_malloced = 0;
+ 		  }
+ 	}
+@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
+ 			  {
+ 			    free (*answerp2);
+ 			    *answerp2 = NULL;
++			    *nanswerp2 = 0;
+ 			    *answerp2_malloced = 0;
+ 			  }
+ 
+@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
+ 	  {
+ 	    free (*answerp2);
+ 	    *answerp2 = NULL;
++	    *nanswerp2 = 0;
+ 	    *answerp2_malloced = 0;
+ 	  }
+ 	if (saved_herrno != -1)
+Index: b/resolv/res_send.c
+===================================================================
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -1,3 +1,20 @@
++/* Copyright (C) 2016 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++
++   The GNU C 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.
++
++   The GNU C 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 the GNU C Library; if not, see
++   <http://www.gnu.org/licenses/>.  */
++
+ /*
+  * Copyright (c) 1985, 1989, 1993
+  *    The Regents of the University of California.  All rights reserved.
+@@ -361,6 +378,8 @@ __libc_res_nsend(res_state statp, const
+ #ifdef USE_HOOKS
+ 	if (__glibc_unlikely (statp->qhook || statp->rhook))       {
+ 		if (anssiz < MAXPACKET && ansp) {
++			/* Always allocate MAXPACKET, callers expect
++			   this specific size.  */
+ 			u_char *buf = malloc (MAXPACKET);
+ 			if (buf == NULL)
+ 				return (-1);
+@@ -660,6 +679,77 @@ libresolv_hidden_def (res_nsend)
+ 
+ /* Private */
+ 
++/* The send_vc function is responsible for sending a DNS query over TCP
++   to the nameserver numbered NS from the res_state STATP i.e.
++   EXT(statp).nssocks[ns].  The function supports sending both IPv4 and
++   IPv6 queries at the same serially on the same socket.
++
++   Please note that for TCP there is no way to disable sending both
++   queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
++   and sends the queries serially and waits for the result after each
++   sent query.  This implemetnation should be corrected to honour these
++   options.
++
++   Please also note that for TCP we send both queries over the same
++   socket one after another.  This technically violates best practice
++   since the server is allowed to read the first query, respond, and
++   then close the socket (to service another client).  If the server
++   does this, then the remaining second query in the socket data buffer
++   will cause the server to send the client an RST which will arrive
++   asynchronously and the client's OS will likely tear down the socket
++   receive buffer resulting in a potentially short read and lost
++   response data.  This will force the client to retry the query again,
++   and this process may repeat until all servers and connection resets
++   are exhausted and then the query will fail.  It's not known if this
++   happens with any frequency in real DNS server implementations.  This
++   implementation should be corrected to use two sockets by default for
++   parallel queries.
++
++   The query stored in BUF of BUFLEN length is sent first followed by
++   the query stored in BUF2 of BUFLEN2 length.  Queries are sent
++   serially on the same socket.
++
++   Answers to the query are stored firstly in *ANSP up to a max of
++   *ANSSIZP bytes.  If more than *ANSSIZP bytes are needed and ANSCP
++   is non-NULL (to indicate that modifying the answer buffer is allowed)
++   then malloc is used to allocate a new response buffer and ANSCP and
++   ANSP will both point to the new buffer.  If more than *ANSSIZP bytes
++   are needed but ANSCP is NULL, then as much of the response as
++   possible is read into the buffer, but the results will be truncated.
++   When truncation happens because of a small answer buffer the DNS
++   packets header feild TC will bet set to 1, indicating a truncated
++   message and the rest of the socket data will be read and discarded.
++
++   Answers to the query are stored secondly in *ANSP2 up to a max of
++   *ANSSIZP2 bytes, with the actual response length stored in
++   *RESPLEN2.  If more than *ANSSIZP bytes are needed and ANSP2
++   is non-NULL (required for a second query) then malloc is used to
++   allocate a new response buffer, *ANSSIZP2 is set to the new buffer
++   size and *ANSP2_MALLOCED is set to 1.
++
++   The ANSP2_MALLOCED argument will eventually be removed as the
++   change in buffer pointer can be used to detect the buffer has
++   changed and that the caller should use free on the new buffer.
++
++   Note that the answers may arrive in any order from the server and
++   therefore the first and second answer buffers may not correspond to
++   the first and second queries.
++
++   It is not supported to call this function with a non-NULL ANSP2
++   but a NULL ANSCP.  Put another way, you can call send_vc with a
++   single unmodifiable buffer or two modifiable buffers, but no other
++   combination is supported.
++
++   It is the caller's responsibility to free the malloc allocated
++   buffers by detecting that the pointers have changed from their
++   original values i.e. *ANSCP or *ANSP2 has changed.
++
++   If errors are encountered then *TERRNO is set to an appropriate
++   errno value and a zero result is returned for a recoverable error,
++   and a less-than zero result is returned for a non-recoverable error.
++
++   If no errors are encountered then *TERRNO is left unmodified and
++   a the length of the first response in bytes is returned.  */
+ static int
+ send_vc(res_state statp,
+ 	const u_char *buf, int buflen, const u_char *buf2, int buflen2,
+@@ -669,11 +759,7 @@ send_vc(res_state statp,
+ {
+ 	const HEADER *hp = (HEADER *) buf;
+ 	const HEADER *hp2 = (HEADER *) buf2;
+-	u_char *ans = *ansp;
+-	int orig_anssizp = *anssizp;
+-	// XXX REMOVE
+-	// int anssiz = *anssizp;
+-	HEADER *anhp = (HEADER *) ans;
++	HEADER *anhp = (HEADER *) *ansp;
+ 	struct sockaddr *nsap = get_nsaddr (statp, ns);
+ 	int truncating, connreset, n;
+ 	/* On some architectures compiler might emit a warning indicating
+@@ -766,6 +852,8 @@ send_vc(res_state statp,
+ 	 * Receive length & response
+ 	 */
+ 	int recvresp1 = 0;
++	/* Skip the second response if there is no second query.
++           To do that we mark the second response as received.  */
+ 	int recvresp2 = buf2 == NULL;
+ 	uint16_t rlen16;
+  read_len:
+@@ -802,40 +890,14 @@ send_vc(res_state statp,
+ 	u_char **thisansp;
+ 	int *thisresplenp;
+ 	if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
++		/* We have not received any responses
++		   yet or we only have one response to
++		   receive.  */
+ 		thisanssizp = anssizp;
+ 		thisansp = anscp ?: ansp;
+ 		assert (anscp != NULL || ansp2 == NULL);
+ 		thisresplenp = &resplen;
+ 	} else {
+-		if (*anssizp != MAXPACKET) {
+-			/* No buffer allocated for the first
+-			   reply.  We can try to use the rest
+-			   of the user-provided buffer.  */
+-#if __GNUC_PREREQ (4, 7)
+-			DIAG_PUSH_NEEDS_COMMENT;
+-			DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
+-#endif
+-#if _STRING_ARCH_unaligned
+-			*anssizp2 = orig_anssizp - resplen;
+-			*ansp2 = *ansp + resplen;
+-#else
+-			int aligned_resplen
+-			  = ((resplen + __alignof__ (HEADER) - 1)
+-			     & ~(__alignof__ (HEADER) - 1));
+-			*anssizp2 = orig_anssizp - aligned_resplen;
+-			*ansp2 = *ansp + aligned_resplen;
+-#endif
+-#if __GNUC_PREREQ (4, 7)
+-			DIAG_POP_NEEDS_COMMENT;
+-#endif
+-		} else {
+-			/* The first reply did not fit into the
+-			   user-provided buffer.  Maybe the second
+-			   answer will.  */
+-			*anssizp2 = orig_anssizp;
+-			*ansp2 = *ansp;
+-		}
+-
+ 		thisanssizp = anssizp2;
+ 		thisansp = ansp2;
+ 		thisresplenp = resplen2;
+@@ -843,10 +905,14 @@ send_vc(res_state statp,
+ 	anhp = (HEADER *) *thisansp;
+ 
+ 	*thisresplenp = rlen;
+-	if (rlen > *thisanssizp) {
+-		/* Yes, we test ANSCP here.  If we have two buffers
+-		   both will be allocatable.  */
+-		if (__glibc_likely (anscp != NULL))       {
++	/* Is the answer buffer too small?  */
++	if (*thisanssizp < rlen) {
++		/* If the current buffer is non-NULL and it's not
++		   pointing at the static user-supplied buffer then
++		   we can reallocate it.  */
++		if (thisansp != NULL && thisansp != ansp) {
++			/* Always allocate MAXPACKET, callers expect
++			   this specific size.  */
+ 			u_char *newp = malloc (MAXPACKET);
+ 			if (newp == NULL) {
+ 				*terrno = ENOMEM;
+@@ -858,6 +924,9 @@ send_vc(res_state statp,
+ 			if (thisansp == ansp2)
+ 			  *ansp2_malloced = 1;
+ 			anhp = (HEADER *) newp;
++			/* A uint16_t can't be larger than MAXPACKET
++			   thus it's safe to allocate MAXPACKET but
++			   read RLEN bytes instead.  */
+ 			len = rlen;
+ 		} else {
+ 			Dprint(statp->options & RES_DEBUG,
+@@ -1021,6 +1090,66 @@ reopen (res_state statp, int *terrno, in
+ 	return 1;
+ }
+ 
++/* The send_dg function is responsible for sending a DNS query over UDP
++   to the nameserver numbered NS from the res_state STATP i.e.
++   EXT(statp).nssocks[ns].  The function supports IPv4 and IPv6 queries
++   along with the ability to send the query in parallel for both stacks
++   (default) or serially (RES_SINGLKUP).  It also supports serial lookup
++   with a close and reopen of the socket used to talk to the server
++   (RES_SNGLKUPREOP) to work around broken name servers.
++
++   The query stored in BUF of BUFLEN length is sent first followed by
++   the query stored in BUF2 of BUFLEN2 length.  Queries are sent
++   in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
++
++   Answers to the query are stored firstly in *ANSP up to a max of
++   *ANSSIZP bytes.  If more than *ANSSIZP bytes are needed and ANSCP
++   is non-NULL (to indicate that modifying the answer buffer is allowed)
++   then malloc is used to allocate a new response buffer and ANSCP and
++   ANSP will both point to the new buffer.  If more than *ANSSIZP bytes
++   are needed but ANSCP is NULL, then as much of the response as
++   possible is read into the buffer, but the results will be truncated.
++   When truncation happens because of a small answer buffer the DNS
++   packets header feild TC will bet set to 1, indicating a truncated
++   message, while the rest of the UDP packet is discarded.
++
++   Answers to the query are stored secondly in *ANSP2 up to a max of
++   *ANSSIZP2 bytes, with the actual response length stored in
++   *RESPLEN2.  If more than *ANSSIZP bytes are needed and ANSP2
++   is non-NULL (required for a second query) then malloc is used to
++   allocate a new response buffer, *ANSSIZP2 is set to the new buffer
++   size and *ANSP2_MALLOCED is set to 1.
++
++   The ANSP2_MALLOCED argument will eventually be removed as the
++   change in buffer pointer can be used to detect the buffer has
++   changed and that the caller should use free on the new buffer.
++
++   Note that the answers may arrive in any order from the server and
++   therefore the first and second answer buffers may not correspond to
++   the first and second queries.
++
++   It is not supported to call this function with a non-NULL ANSP2
++   but a NULL ANSCP.  Put another way, you can call send_vc with a
++   single unmodifiable buffer or two modifiable buffers, but no other
++   combination is supported.
++
++   It is the caller's responsibility to free the malloc allocated
++   buffers by detecting that the pointers have changed from their
++   original values i.e. *ANSCP or *ANSP2 has changed.
++
++   If an answer is truncated because of UDP datagram DNS limits then
++   *V_CIRCUIT is set to 1 and the return value non-zero to indicate to
++   the caller to retry with TCP.  The value *GOTSOMEWHERE is set to 1
++   if any progress was made reading a response from the nameserver and
++   is used by the caller to distinguish between ECONNREFUSED and
++   ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
++
++   If errors are encountered then *TERRNO is set to an appropriate
++   errno value and a zero result is returned for a recoverable error,
++   and a less-than zero result is returned for a non-recoverable error.
++
++   If no errors are encountered then *TERRNO is left unmodified and
++   a the length of the first response in bytes is returned.  */
+ static int
+ send_dg(res_state statp,
+ 	const u_char *buf, int buflen, const u_char *buf2, int buflen2,
+@@ -1030,8 +1159,6 @@ send_dg(res_state statp,
+ {
+ 	const HEADER *hp = (HEADER *) buf;
+ 	const HEADER *hp2 = (HEADER *) buf2;
+-	u_char *ans = *ansp;
+-	int orig_anssizp = *anssizp;
+ 	struct timespec now, timeout, finish;
+ 	struct pollfd pfd[1];
+ 	int ptimeout;
+@@ -1064,6 +1191,8 @@ send_dg(res_state statp,
+ 	int need_recompute = 0;
+ 	int nwritten = 0;
+ 	int recvresp1 = 0;
++	/* Skip the second response if there is no second query.
++           To do that we mark the second response as received.  */
+ 	int recvresp2 = buf2 == NULL;
+ 	pfd[0].fd = EXT(statp).nssocks[ns];
+ 	pfd[0].events = POLLOUT;
+@@ -1227,55 +1356,56 @@ send_dg(res_state statp,
+ 		int *thisresplenp;
+ 
+ 		if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
++			/* We have not received any responses
++			   yet or we only have one response to
++			   receive.  */
+ 			thisanssizp = anssizp;
+ 			thisansp = anscp ?: ansp;
+ 			assert (anscp != NULL || ansp2 == NULL);
+ 			thisresplenp = &resplen;
+ 		} else {
+-			if (*anssizp != MAXPACKET) {
+-				/* No buffer allocated for the first
+-				   reply.  We can try to use the rest
+-				   of the user-provided buffer.  */
+-#if _STRING_ARCH_unaligned
+-				*anssizp2 = orig_anssizp - resplen;
+-				*ansp2 = *ansp + resplen;
+-#else
+-				int aligned_resplen
+-				  = ((resplen + __alignof__ (HEADER) - 1)
+-				     & ~(__alignof__ (HEADER) - 1));
+-				*anssizp2 = orig_anssizp - aligned_resplen;
+-				*ansp2 = *ansp + aligned_resplen;
+-#endif
+-			} else {
+-				/* The first reply did not fit into the
+-				   user-provided buffer.  Maybe the second
+-				   answer will.  */
+-				*anssizp2 = orig_anssizp;
+-				*ansp2 = *ansp;
+-			}
+-
+ 			thisanssizp = anssizp2;
+ 			thisansp = ansp2;
+ 			thisresplenp = resplen2;
+ 		}
+ 
+ 		if (*thisanssizp < MAXPACKET
+-		    /* Yes, we test ANSCP here.  If we have two buffers
+-		       both will be allocatable.  */
+-		    && anscp
++		    /* If the current buffer is non-NULL and it's not
++		       pointing at the static user-supplied buffer then
++		       we can reallocate it.  */
++		    && (thisansp != NULL && thisansp != ansp)
+ #ifdef FIONREAD
++		    /* Is the size too small?  */
+ 		    && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
+ 			|| *thisanssizp < *thisresplenp)
+ #endif
+                     ) {
++			/* Always allocate MAXPACKET, callers expect
++			   this specific size.  */
+ 			u_char *newp = malloc (MAXPACKET);
+ 			if (newp != NULL) {
+-				*anssizp = MAXPACKET;
+-				*thisansp = ans = newp;
++				*thisanssizp = MAXPACKET;
++				*thisansp = newp;
+ 				if (thisansp == ansp2)
+ 				  *ansp2_malloced = 1;
+ 			}
+ 		}
++		/* We could end up with truncation if anscp was NULL
++		   (not allowed to change caller's buffer) and the
++		   response buffer size is too small.  This isn't a
++		   reliable way to detect truncation because the ioctl
++		   may be an inaccurate report of the UDP message size.
++		   Therefore we use this only to issue debug output.
++		   To do truncation accurately with UDP we need
++		   MSG_TRUNC which is only available on Linux.  We
++		   can abstract out the Linux-specific feature in the
++		   future to detect truncation.  */
++		if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
++			Dprint(statp->options & RES_DEBUG,
++			       (stdout, ";; response may be truncated (UDP)\n")
++			);
++		}
++
+ 		HEADER *anhp = (HEADER *) *thisansp;
+ 		socklen_t fromlen = sizeof(struct sockaddr_in6);
+ 		assert (sizeof(from) <= fromlen);
diff --git a/gnu/packages/patches/gnupg-simple-query-ignore-status-messages.patch b/gnu/packages/patches/gnupg-simple-query-ignore-status-messages.patch
new file mode 100644
index 0000000000..153f71c38f
--- /dev/null
+++ b/gnu/packages/patches/gnupg-simple-query-ignore-status-messages.patch
@@ -0,0 +1,142 @@
+Copied from upstream:
+http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=commitdiff;h=acac103ba5772ae738ce5409d17feab80596cde6
+
+Fixes: https://debbugs.gnu.org/22558
+Upstream bug: https://bugs.gnupg.org/gnupg/issue2229
+
+From acac103ba5772ae738ce5409d17feab80596cde6 Mon Sep 17 00:00:00 2001
+From: "Neal H. Walfield" <neal@g10code.com>
+Date: Fri, 12 Feb 2016 22:12:21 +0100
+Subject: [PATCH] common: Change simple_query to ignore status messages.
+
+* common/simple-pwquery.c (simple_query): Ignore status messages.
+
+--
+Signed-off-by: Neal H. Walfield <neal@g10code.com>
+GnuPG-bug-id: 2229
+---
+ common/simple-pwquery.c | 95 ++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 67 insertions(+), 28 deletions(-)
+
+diff --git a/common/simple-pwquery.c b/common/simple-pwquery.c
+index 90d04c0..b2d666c 100644
+--- a/common/simple-pwquery.c
++++ b/common/simple-pwquery.c
+@@ -618,6 +618,7 @@ simple_query (const char *query)
+   int fd = -1;
+   int nread;
+   char response[500];
++  int have = 0;
+   int rc;
+ 
+   rc = agent_open (&fd);
+@@ -628,40 +629,78 @@ simple_query (const char *query)
+   if (rc)
+     goto leave;
+ 
+-  /* get response */
+-  nread = readline (fd, response, 499);
+-  if (nread < 0)
+-    {
+-      rc = -nread;
+-      goto leave;
+-    }
+-  if (nread < 3)
++  while (1)
+     {
+-      rc = SPWQ_PROTOCOL_ERROR;
+-      goto leave;
+-    }
++      if (! have || ! strchr (response, '\n'))
++        /* get response */
++        {
++          nread = readline (fd, &response[have],
++                            sizeof (response) - 1 /* NUL */ - have);
++          if (nread < 0)
++            {
++              rc = -nread;
++              goto leave;
++            }
++          have += nread;
++          if (have < 3)
++            {
++              rc = SPWQ_PROTOCOL_ERROR;
++              goto leave;
++            }
++          response[have] = 0;
++        }
+ 
+-  if (response[0] == 'O' && response[1] == 'K')
+-    /* OK, do nothing.  */;
+-  else if ((nread > 7 && !memcmp (response, "ERR 111", 7)
+-            && (response[7] == ' ' || response[7] == '\n') )
+-           || ((nread > 4 && !memcmp (response, "ERR ", 4)
+-                && (strtoul (response+4, NULL, 0) & 0xffff) == 99)) )
+-    {
+-      /* 111 is the old Assuan code for canceled which might still
+-         be in use by old installations. 99 is GPG_ERR_CANCELED as
+-         used by modern gpg-agents; 0xffff is used to mask out the
+-         error source.  */
++      if (response[0] == 'O' && response[1] == 'K')
++        /* OK, do nothing.  */;
++      else if ((nread > 7 && !memcmp (response, "ERR 111", 7)
++                && (response[7] == ' ' || response[7] == '\n') )
++               || ((nread > 4 && !memcmp (response, "ERR ", 4)
++                    && (strtoul (response+4, NULL, 0) & 0xffff) == 99)) )
++        {
++          /* 111 is the old Assuan code for canceled which might still
++             be in use by old installations. 99 is GPG_ERR_CANCELED as
++             used by modern gpg-agents; 0xffff is used to mask out the
++             error source.  */
+ #ifdef SPWQ_USE_LOGGING
+-      log_info (_("canceled by user\n") );
++          log_info (_("canceled by user\n") );
+ #endif
+-    }
+-  else
+-    {
++        }
++      else if (response[0] == 'S' && response[1] == ' ')
++        {
++          char *nextline;
++          int consumed;
++
++          nextline = strchr (response, '\n');
++          if (! nextline)
++            /* Point to the NUL.  */
++            nextline = &response[have];
++          else
++            /* Move past the \n.  */
++            nextline ++;
++
++          consumed = (size_t) nextline - (size_t) response;
++
++          /* Skip any additional newlines.  */
++          while (consumed < have && response[consumed] == '\n')
++            consumed ++;
++
++          have -= consumed;
++
++          if (have)
++            memmove (response, &response[consumed], have + 1);
++
++          continue;
++        }
++      else
++        {
+ #ifdef SPWQ_USE_LOGGING
+-      log_error (_("problem with the agent\n"));
++          log_error (_("problem with the agent (unexpected response \"%s\"\n"),
++                     response);
+ #endif
+-      rc = SPWQ_ERR_RESPONSE;
++          rc = SPWQ_ERR_RESPONSE;
++        }
++
++      break;
+     }
+ 
+  leave:
+-- 
+2.6.3
+
diff --git a/gnu/packages/patches/icecat-update-graphite2.patch b/gnu/packages/patches/icecat-update-graphite2.patch
new file mode 100644
index 0000000000..af2c47bef7
--- /dev/null
+++ b/gnu/packages/patches/icecat-update-graphite2.patch
@@ -0,0 +1,9988 @@
+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/libsndfile-CVE-2014-9496.patch b/gnu/packages/patches/libsndfile-CVE-2014-9496.patch
deleted file mode 100644
index 87d42955fb..0000000000
--- a/gnu/packages/patches/libsndfile-CVE-2014-9496.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-Copied from Fedora.
-
-http://pkgs.fedoraproject.org/cgit/libsndfile.git/plain/libsndfile-1.0.25-cve2014_9496.patch
-
-diff -up libsndfile-1.0.25/src/sd2.c.cve2014_9496 libsndfile-1.0.25/src/sd2.c
---- libsndfile-1.0.25/src/sd2.c.cve2014_9496	2011-01-19 11:10:36.000000000 +0100
-+++ libsndfile-1.0.25/src/sd2.c	2015-01-13 17:00:35.920285526 +0100
-@@ -395,6 +395,21 @@ read_marker (const unsigned char * data,
- 		return 0x666 ;
- } /* read_marker */
- 
-+static inline int
-+read_rsrc_marker (const SD2_RSRC *prsrc, int offset)
-+{	const unsigned char * data = prsrc->rsrc_data ;
-+
-+	if (offset < 0 || offset + 3 >= prsrc->rsrc_len)
-+		return 0 ;
-+
-+	if (CPU_IS_BIG_ENDIAN)
-+		return (((uint32_t) data [offset]) << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
-+	if (CPU_IS_LITTLE_ENDIAN)
-+		return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (((uint32_t) data [offset + 3]) << 24) ;
-+
-+	return 0 ;
-+} /* read_rsrc_marker */
-+
- static void
- read_str (const unsigned char * data, int offset, char * buffer, int buffer_len)
- {	int k ;
-@@ -496,6 +511,11 @@ sd2_parse_rsrc_fork (SF_PRIVATE *psf)
- 
- 	rsrc.type_offset = rsrc.map_offset + 30 ;
- 
-+	if (rsrc.map_offset + 28 > rsrc.rsrc_len)
-+	{       psf_log_printf (psf, "Bad map offset.\n") ;
-+		goto parse_rsrc_fork_cleanup ;
-+		} ;
-+
- 	rsrc.type_count = read_short (rsrc.rsrc_data, rsrc.map_offset + 28) + 1 ;
- 	if (rsrc.type_count < 1)
- 	{	psf_log_printf (psf, "Bad type count.\n") ;
-@@ -512,7 +532,12 @@ sd2_parse_rsrc_fork (SF_PRIVATE *psf)
- 
- 	rsrc.str_index = -1 ;
- 	for (k = 0 ; k < rsrc.type_count ; k ++)
--	{	marker = read_marker (rsrc.rsrc_data, rsrc.type_offset + k * 8) ;
-+	{	if (rsrc.type_offset + k * 8 > rsrc.rsrc_len)
-+		{	psf_log_printf (psf, "Bad rsrc marker.\n") ;
-+			goto parse_rsrc_fork_cleanup ;
-+			} ;
-+
-+		marker = read_rsrc_marker (&rsrc, rsrc.type_offset + k * 8) ;
- 
- 		if (marker == STR_MARKER)
- 		{	rsrc.str_index = k ;
diff --git a/gnu/packages/patches/libsndfile-CVE-2015-7805.patch b/gnu/packages/patches/libsndfile-CVE-2015-7805.patch
deleted file mode 100644
index d617f81e5c..0000000000
--- a/gnu/packages/patches/libsndfile-CVE-2015-7805.patch
+++ /dev/null
@@ -1,95 +0,0 @@
-Slightly modified to apply cleanly to libsndfile-1.0.25.
-
-From d2a87385c1ca1d72918e9a2875d24f202a5093e8 Mon Sep 17 00:00:00 2001
-From: Erik de Castro Lopo <erikd@mega-nerd.com>
-Date: Sat, 7 Feb 2015 15:45:10 +1100
-Subject: [PATCH] src/common.c : Fix a header parsing bug.
-
-When the file header is bigger that SF_HEADER_LEN, the code would seek
-instead of reading causing file parse errors.
-
-The current header parsing and writing code *badly* needs a re-write.
----
- src/common.c | 27 +++++++++++----------------
- 1 file changed, 11 insertions(+), 16 deletions(-)
-
-diff --git a/src/common.c b/src/common.c
-index dd4edb7..c6b88cc 100644
---- a/src/common.c
-+++ b/src/common.c
-@@ -1,5 +1,5 @@
- /*
--** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
-+** Copyright (C) 1999-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU Lesser General Public License as published by
-@@ -800,21 +800,16 @@ header_read (SF_PRIVATE *psf, void *ptr, int bytes)
- {	int count = 0 ;
- 
- 	if (psf->headindex >= SIGNED_SIZEOF (psf->header))
--	{	memset (ptr, 0, SIGNED_SIZEOF (psf->header) - psf->headindex) ;
--
--		/* This is the best that we can do. */
--		psf_fseek (psf, bytes, SEEK_CUR) ;
--		return bytes ;
--		} ;
-+		return psf_fread (ptr, 1, bytes, psf) ;
- 
- 	if (psf->headindex + bytes > SIGNED_SIZEOF (psf->header))
- 	{	int most ;
- 
- 		most = SIGNED_SIZEOF (psf->header) - psf->headindex ;
- 		psf_fread (psf->header + psf->headend, 1, most, psf) ;
--		memset ((char *) ptr + most, 0, bytes - most) ;
--
--		psf_fseek (psf, bytes - most, SEEK_CUR) ;
-+		memcpy (ptr, psf->header + psf->headend, most) ;
-+		psf->headend = psf->headindex += most ;
-+		psf_fread ((char *) ptr + most, bytes - most, 1, psf) ;
- 		return bytes ;
- 		} ;
- 
-@@ -822,7 +817,7 @@ header_read (SF_PRIVATE *psf, void *ptr, int bytes)
- 	{	count = psf_fread (psf->header + psf->headend, 1, bytes - (psf->headend - psf->headindex), psf) ;
- 		if (count != bytes - (int) (psf->headend - psf->headindex))
- 		{	psf_log_printf (psf, "Error : psf_fread returned short count.\n") ;
--			return 0 ;
-+			return count ;
- 			} ;
- 		psf->headend += count ;
- 		} ;
-@@ -836,7 +831,6 @@ header_read (SF_PRIVATE *psf, void *ptr, int bytes)
- static void
- header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
- {
--
- 	switch (whence)
- 	{	case SEEK_SET :
- 			if (position > SIGNED_SIZEOF (psf->header))
-@@ -885,8 +879,7 @@ header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
- 
- static int
- header_gets (SF_PRIVATE *psf, char *ptr, int bufsize)
--{
--	int		k ;
-+{	int		k ;
- 
- 	for (k = 0 ; k < bufsize - 1 ; k++)
- 	{	if (psf->headindex < psf->headend)
-@@ -1073,8 +1066,10 @@ psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
- 			case 'j' :
- 					/* Get the seek position first. */
- 					count = va_arg (argptr, size_t) ;
--					header_seek (psf, count, SEEK_CUR) ;
--					byte_count += count ;
-+					if (count)
-+					{	header_seek (psf, count, SEEK_CUR) ;
-+						byte_count += count ;
-+						} ;
- 					break ;
- 
- 			default :
--- 
-2.6.3
-
diff --git a/gnu/packages/patches/libssh-0.6.5-CVE-2016-0739.patch b/gnu/packages/patches/libssh-0.6.5-CVE-2016-0739.patch
new file mode 100644
index 0000000000..a5fdd7ffff
--- /dev/null
+++ b/gnu/packages/patches/libssh-0.6.5-CVE-2016-0739.patch
@@ -0,0 +1,77 @@
+Fix CVE-2016-0739 (Weak Diffie-Hellman secret generation in
+dh_generate_x() and dh_generate_y()).
+
+"Due to a byte/bit confusion, the DH secret was too short. This file was
+completely reworked and will be commited in a future version."
+Source:
+https://git.libssh.org/projects/libssh.git/commit/?id=f8d0026c65fc8a55748ae481758e2cf376c26c86
+
+This patch was created by upstream for libssh-0.7.3, but applied without
+modification to libssh-0.6.3 by Debian. In Guix, we apply it without
+modification to libssh-0.6.5.
+
+References:
+https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-0739
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-0739
+https://security-tracker.debian.org/tracker/CVE-2016-0739
+
+---
+ src/dh.c | 22 +++++++++++++++++-----
+ 1 file changed, 17 insertions(+), 5 deletions(-)
+
+diff --git a/src/dh.c b/src/dh.c
+index e489a1d..d27b66e 100644
+--- a/src/dh.c
++++ b/src/dh.c
+@@ -227,15 +227,21 @@ void ssh_crypto_finalize(void) {
+ }
+ 
+ int dh_generate_x(ssh_session session) {
++  int keysize;
++  if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
++    keysize = 1023;
++  } else {
++    keysize = 2047;
++  }
+   session->next_crypto->x = bignum_new();
+   if (session->next_crypto->x == NULL) {
+     return -1;
+   }
+ 
+ #ifdef HAVE_LIBGCRYPT
+-  bignum_rand(session->next_crypto->x, 128);
++  bignum_rand(session->next_crypto->x, keysize);
+ #elif defined HAVE_LIBCRYPTO
+-  bignum_rand(session->next_crypto->x, 128, 0, -1);
++  bignum_rand(session->next_crypto->x, keysize, -1, 0);
+ #endif
+ 
+   /* not harder than this */
+@@ -248,15 +254,21 @@ int dh_generate_x(ssh_session session) {
+ 
+ /* used by server */
+ int dh_generate_y(ssh_session session) {
+-    session->next_crypto->y = bignum_new();
++  int keysize;
++  if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
++    keysize = 1023;
++  } else {
++    keysize = 2047;
++  }
++  session->next_crypto->y = bignum_new();
+   if (session->next_crypto->y == NULL) {
+     return -1;
+   }
+ 
+ #ifdef HAVE_LIBGCRYPT
+-  bignum_rand(session->next_crypto->y, 128);
++  bignum_rand(session->next_crypto->y, keysize);
+ #elif defined HAVE_LIBCRYPTO
+-  bignum_rand(session->next_crypto->y, 128, 0, -1);
++  bignum_rand(session->next_crypto->y, keysize, -1, 0);
+ #endif
+ 
+   /* not harder than this */
+-- 
+cgit v0.12
+
diff --git a/gnu/packages/patches/libssh-CVE-2014-0017.patch b/gnu/packages/patches/libssh-CVE-2014-0017.patch
deleted file mode 100644
index 94d8cc33d2..0000000000
--- a/gnu/packages/patches/libssh-CVE-2014-0017.patch
+++ /dev/null
@@ -1,89 +0,0 @@
-Patch from libssh 0.6, with bind.c hunk adjusted for 0.5.5.
-
-From e99246246b4061f7e71463f8806b9dcad65affa0 Mon Sep 17 00:00:00 2001
-From: Aris Adamantiadis <aris@0xbadc0de.be>
-Date: Wed, 05 Feb 2014 20:24:12 +0000
-Subject: security: fix for vulnerability CVE-2014-0017
-
-When accepting a new connection, a forking server based on libssh forks
-and the child process handles the request. The RAND_bytes() function of
-openssl doesn't reset its state after the fork, but simply adds the
-current process id (getpid) to the PRNG state, which is not guaranteed
-to be unique.
-This can cause several children to end up with same PRNG state which is
-a security issue.
----
-diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
-index 7374a88..e8ff32c 100644
---- a/include/libssh/wrapper.h
-+++ b/include/libssh/wrapper.h
-@@ -70,5 +70,6 @@ int crypt_set_algorithms_server(ssh_session session);
- struct ssh_crypto_struct *crypto_new(void);
- void crypto_free(struct ssh_crypto_struct *crypto);
- 
-+void ssh_reseed(void);
- 
- #endif /* WRAPPER_H_ */
-diff --git a/src/bind.c b/src/bind.c
-index 8d82d0d..03d3403 100644
---- a/src/bind.c
-+++ b/src/bind.c
-@@ -375,6 +375,8 @@ int ssh_bind_accept(ssh_bind sshbind, ss
-   session->dsa_key = dsa;
-   session->rsa_key = rsa;
- 
-+  /* force PRNG to change state in case we fork after ssh_bind_accept */
-+  ssh_reseed();
-   return SSH_OK;
- }
- 
-diff --git a/src/libcrypto.c b/src/libcrypto.c
-index bb1d96a..d8cc795 100644
---- a/src/libcrypto.c
-+++ b/src/libcrypto.c
-@@ -23,6 +23,7 @@
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-+#include <sys/time.h>
- 
- #include "libssh/priv.h"
- #include "libssh/session.h"
-@@ -38,6 +39,8 @@
- #include <openssl/rsa.h>
- #include <openssl/hmac.h>
- #include <openssl/opensslv.h>
-+#include <openssl/rand.h>
-+
- #ifdef HAVE_OPENSSL_AES_H
- #define HAS_AES
- #include <openssl/aes.h>
-@@ -74,6 +77,12 @@ static int alloc_key(struct ssh_cipher_struct *cipher) {
-     return 0;
- }
- 
-+void ssh_reseed(void){
-+    struct timeval tv;
-+    gettimeofday(&tv, NULL);
-+    RAND_add(&tv, sizeof(tv), 0.0);
-+}
-+
- SHACTX sha1_init(void) {
-   SHACTX c = malloc(sizeof(*c));
-   if (c == NULL) {
-diff --git a/src/libgcrypt.c b/src/libgcrypt.c
-index 899bccd..4617901 100644
---- a/src/libgcrypt.c
-+++ b/src/libgcrypt.c
-@@ -45,6 +45,9 @@ static int alloc_key(struct ssh_cipher_struct *cipher) {
-     return 0;
- }
- 
-+void ssh_reseed(void){
-+	}
-+
- SHACTX sha1_init(void) {
-   SHACTX ctx = NULL;
-   gcry_md_open(&ctx, GCRY_MD_SHA1, 0);
---
-cgit v0.9.1
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-2695-pt1.patch b/gnu/packages/patches/mit-krb5-CVE-2015-2695-pt1.patch
deleted file mode 100644
index 0f5603e228..0000000000
--- a/gnu/packages/patches/mit-krb5-CVE-2015-2695-pt1.patch
+++ /dev/null
@@ -1,569 +0,0 @@
-Copied from Debian.
-
-From b813d5811432faed844a2dfd3daecde914978f2c Mon Sep 17 00:00:00 2001
-From: Nicolas Williams <nico@twosigma.com>
-Date: Mon, 14 Sep 2015 12:27:52 -0400
-Subject: Fix SPNEGO context aliasing bugs [CVE-2015-2695]
-
-The SPNEGO mechanism currently replaces its context handle with the
-mechanism context handle upon establishment, under the assumption that
-most GSS functions are only called after context establishment.  This
-assumption is incorrect, and can lead to aliasing violations for some
-programs.  Maintain the SPNEGO context structure after context
-establishment and refer to it in all GSS methods.  Add initiate and
-opened flags to the SPNEGO context structure for use in
-gss_inquire_context() prior to context establishment.
-
-CVE-2015-2695:
-
-In MIT krb5 1.5 and later, applications which call
-gss_inquire_context() on a partially-established SPNEGO context can
-cause the GSS-API library to read from a pointer using the wrong type,
-generally causing a process crash.  This bug may go unnoticed, because
-the most common SPNEGO authentication scenario establishes the context
-after just one call to gss_accept_sec_context().  Java server
-applications using the native JGSS provider are vulnerable to this
-bug.  A carefully crafted SPNEGO packet might allow the
-gss_inquire_context() call to succeed with attacker-determined
-results, but applications should not make access control decisions
-based on gss_inquire_context() results prior to context establishment.
-
-    CVSSv2 Vector: AV:N/AC:M/Au:N/C:N/I:N/A:C/E:POC/RL:OF/RC:C
-
-[ghudson@mit.edu: several bugfixes, style changes, and edge-case
-behavior changes; commit message and CVE description]
-
-ticket: 8244
-target_version: 1.14
-tags: pullup
-
-(cherry picked from commit b51b33f2bc5d1497ddf5bd107f791c101695000d)
-Patch-Category: upstream
----
- src/lib/gssapi/spnego/gssapiP_spnego.h |   2 +
- src/lib/gssapi/spnego/spnego_mech.c    | 254 ++++++++++++++++++++++++---------
- 2 files changed, 192 insertions(+), 64 deletions(-)
-
-diff --git a/src/lib/gssapi/spnego/gssapiP_spnego.h b/src/lib/gssapi/spnego/gssapiP_spnego.h
-index bc23f56..8e05736 100644
---- a/src/lib/gssapi/spnego/gssapiP_spnego.h
-+++ b/src/lib/gssapi/spnego/gssapiP_spnego.h
-@@ -102,6 +102,8 @@ typedef struct {
- 	int firstpass;
- 	int mech_complete;
- 	int nego_done;
-+	int initiate;
-+	int opened;
- 	OM_uint32 ctx_flags;
- 	gss_name_t internal_name;
- 	gss_OID actual_mech;
-diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
-index 6e39c37..a1072b0 100644
---- a/src/lib/gssapi/spnego/spnego_mech.c
-+++ b/src/lib/gssapi/spnego/spnego_mech.c
-@@ -104,7 +104,7 @@ static OM_uint32 get_negotiable_mechs(OM_uint32 *, spnego_gss_cred_id_t,
- 				      gss_cred_usage_t, gss_OID_set *);
- static void release_spnego_ctx(spnego_gss_ctx_id_t *);
- static void check_spnego_options(spnego_gss_ctx_id_t);
--static spnego_gss_ctx_id_t create_spnego_ctx(void);
-+static spnego_gss_ctx_id_t create_spnego_ctx(int);
- static int put_mech_set(gss_OID_set mechSet, gss_buffer_t buf);
- static int put_input_token(unsigned char **, gss_buffer_t, unsigned int);
- static int put_mech_oid(unsigned char **, gss_OID_const, unsigned int);
-@@ -442,7 +442,7 @@ check_spnego_options(spnego_gss_ctx_id_t spnego_ctx)
- }
- 
- static spnego_gss_ctx_id_t
--create_spnego_ctx(void)
-+create_spnego_ctx(int initiate)
- {
- 	spnego_gss_ctx_id_t spnego_ctx = NULL;
- 	spnego_ctx = (spnego_gss_ctx_id_t)
-@@ -465,6 +465,8 @@ create_spnego_ctx(void)
- 	spnego_ctx->mic_rcvd = 0;
- 	spnego_ctx->mech_complete = 0;
- 	spnego_ctx->nego_done = 0;
-+	spnego_ctx->opened = 0;
-+	spnego_ctx->initiate = initiate;
- 	spnego_ctx->internal_name = GSS_C_NO_NAME;
- 	spnego_ctx->actual_mech = GSS_C_NO_OID;
- 
-@@ -630,7 +632,7 @@ init_ctx_new(OM_uint32 *minor_status,
- 	OM_uint32 ret;
- 	spnego_gss_ctx_id_t sc = NULL;
- 
--	sc = create_spnego_ctx();
-+	sc = create_spnego_ctx(1);
- 	if (sc == NULL)
- 		return GSS_S_FAILURE;
- 
-@@ -647,10 +649,7 @@ init_ctx_new(OM_uint32 *minor_status,
- 		ret = GSS_S_FAILURE;
- 		goto cleanup;
- 	}
--	/*
--	 * The actual context is not yet determined, set the output
--	 * context handle to refer to the spnego context itself.
--	 */
-+
- 	sc->ctx_handle = GSS_C_NO_CONTEXT;
- 	*ctx = (gss_ctx_id_t)sc;
- 	sc = NULL;
-@@ -1091,16 +1090,11 @@ cleanup:
- 	}
- 	gss_release_buffer(&tmpmin, &mechtok_out);
- 	if (ret == GSS_S_COMPLETE) {
--		/*
--		 * Now, switch the output context to refer to the
--		 * negotiated mechanism's context.
--		 */
--		*context_handle = (gss_ctx_id_t)spnego_ctx->ctx_handle;
-+		spnego_ctx->opened = 1;
- 		if (actual_mech != NULL)
- 			*actual_mech = spnego_ctx->actual_mech;
- 		if (ret_flags != NULL)
- 			*ret_flags = spnego_ctx->ctx_flags;
--		release_spnego_ctx(&spnego_ctx);
- 	} else if (ret != GSS_S_CONTINUE_NEEDED) {
- 		if (spnego_ctx != NULL) {
- 			gss_delete_sec_context(&tmpmin,
-@@ -1344,7 +1338,7 @@ acc_ctx_hints(OM_uint32 *minor_status,
- 	if (ret != GSS_S_COMPLETE)
- 		goto cleanup;
- 
--	sc = create_spnego_ctx();
-+	sc = create_spnego_ctx(0);
- 	if (sc == NULL) {
- 		ret = GSS_S_FAILURE;
- 		goto cleanup;
-@@ -1426,7 +1420,7 @@ acc_ctx_new(OM_uint32 *minor_status,
- 		gss_release_buffer(&tmpmin, &sc->DER_mechTypes);
- 		assert(mech_wanted != GSS_C_NO_OID);
- 	} else
--		sc = create_spnego_ctx();
-+		sc = create_spnego_ctx(0);
- 	if (sc == NULL) {
- 		ret = GSS_S_FAILURE;
- 		*return_token = NO_TOKEN_SEND;
-@@ -1809,13 +1803,12 @@ cleanup:
- 			ret = GSS_S_FAILURE;
- 	}
- 	if (ret == GSS_S_COMPLETE) {
--		*context_handle = (gss_ctx_id_t)sc->ctx_handle;
-+		sc->opened = 1;
- 		if (sc->internal_name != GSS_C_NO_NAME &&
- 		    src_name != NULL) {
- 			*src_name = sc->internal_name;
- 			sc->internal_name = GSS_C_NO_NAME;
- 		}
--		release_spnego_ctx(&sc);
- 	} else if (ret != GSS_S_CONTINUE_NEEDED) {
- 		if (sc != NULL) {
- 			gss_delete_sec_context(&tmpmin, &sc->ctx_handle,
-@@ -2128,8 +2121,13 @@ spnego_gss_unwrap(
- 		gss_qop_t *qop_state)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_unwrap(minor_status,
--			context_handle,
-+			sc->ctx_handle,
- 			input_message_buffer,
- 			output_message_buffer,
- 			conf_state,
-@@ -2149,8 +2147,13 @@ spnego_gss_wrap(
- 		gss_buffer_t output_message_buffer)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_wrap(minor_status,
--		    context_handle,
-+		    sc->ctx_handle,
- 		    conf_req_flag,
- 		    qop_req,
- 		    input_message_buffer,
-@@ -2167,8 +2170,14 @@ spnego_gss_process_context_token(
- 				const gss_buffer_t token_buffer)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	/* SPNEGO doesn't have its own context tokens. */
-+	if (!sc->opened)
-+		return (GSS_S_DEFECTIVE_TOKEN);
-+
- 	ret = gss_process_context_token(minor_status,
--					context_handle,
-+					sc->ctx_handle,
- 					token_buffer);
- 
- 	return (ret);
-@@ -2192,19 +2201,9 @@ spnego_gss_delete_sec_context(
- 	if (*ctx == NULL)
- 		return (GSS_S_COMPLETE);
- 
--	/*
--	 * If this is still an SPNEGO mech, release it locally.
--	 */
--	if ((*ctx)->magic_num == SPNEGO_MAGIC_ID) {
--		(void) gss_delete_sec_context(minor_status,
--				    &(*ctx)->ctx_handle,
--				    output_token);
--		(void) release_spnego_ctx(ctx);
--	} else {
--		ret = gss_delete_sec_context(minor_status,
--				    context_handle,
--				    output_token);
--	}
-+	(void) gss_delete_sec_context(minor_status, &(*ctx)->ctx_handle,
-+				      output_token);
-+	(void) release_spnego_ctx(ctx);
- 
- 	return (ret);
- }
-@@ -2216,8 +2215,13 @@ spnego_gss_context_time(
- 			OM_uint32	*time_rec)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_context_time(minor_status,
--			    context_handle,
-+			    sc->ctx_handle,
- 			    time_rec);
- 	return (ret);
- }
-@@ -2229,9 +2233,20 @@ spnego_gss_export_sec_context(
- 			    gss_buffer_t interprocess_token)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = *(spnego_gss_ctx_id_t *)context_handle;
-+
-+	/* We don't currently support exporting partially established
-+	 * contexts. */
-+	if (!sc->opened)
-+		return GSS_S_UNAVAILABLE;
-+
- 	ret = gss_export_sec_context(minor_status,
--				    context_handle,
-+				    &sc->ctx_handle,
- 				    interprocess_token);
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT) {
-+		release_spnego_ctx(&sc);
-+		*context_handle = GSS_C_NO_CONTEXT;
-+	}
- 	return (ret);
- }
- 
-@@ -2241,11 +2256,12 @@ spnego_gss_import_sec_context(
- 	const gss_buffer_t	interprocess_token,
- 	gss_ctx_id_t		*context_handle)
- {
--	OM_uint32 ret;
--	ret = gss_import_sec_context(minor_status,
--				    interprocess_token,
--				    context_handle);
--	return (ret);
-+	/*
-+	 * Until we implement partial context exports, there are no SPNEGO
-+	 * exported context tokens, only tokens for underlying mechs.  So just
-+	 * return an error for now.
-+	 */
-+	return GSS_S_UNAVAILABLE;
- }
- #endif /* LEAN_CLIENT */
- 
-@@ -2262,16 +2278,48 @@ spnego_gss_inquire_context(
- 			int		*opened)
- {
- 	OM_uint32 ret = GSS_S_COMPLETE;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (src_name != NULL)
-+		*src_name = GSS_C_NO_NAME;
-+	if (targ_name != NULL)
-+		*targ_name = GSS_C_NO_NAME;
-+	if (lifetime_rec != NULL)
-+		*lifetime_rec = 0;
-+	if (mech_type != NULL)
-+		*mech_type = (gss_OID)gss_mech_spnego;
-+	if (ctx_flags != NULL)
-+		*ctx_flags = 0;
-+	if (locally_initiated != NULL)
-+		*locally_initiated = sc->initiate;
-+	if (opened != NULL)
-+		*opened = sc->opened;
-+
-+	if (sc->ctx_handle != GSS_C_NO_CONTEXT) {
-+		ret = gss_inquire_context(minor_status, sc->ctx_handle,
-+					  src_name, targ_name, lifetime_rec,
-+					  mech_type, ctx_flags, NULL, NULL);
-+	}
- 
--	ret = gss_inquire_context(minor_status,
--				context_handle,
--				src_name,
--				targ_name,
--				lifetime_rec,
--				mech_type,
--				ctx_flags,
--				locally_initiated,
--				opened);
-+	if (!sc->opened) {
-+		/*
-+		 * We are still doing SPNEGO negotiation, so report SPNEGO as
-+		 * the OID.  After negotiation is complete we will report the
-+		 * underlying mechanism OID.
-+		 */
-+		if (mech_type != NULL)
-+			*mech_type = (gss_OID)gss_mech_spnego;
-+
-+		/*
-+		 * Remove flags we don't support with partially-established
-+		 * contexts.  (Change this to keep GSS_C_TRANS_FLAG if we add
-+		 * support for exporting partial SPNEGO contexts.)
-+		 */
-+		if (ctx_flags != NULL) {
-+			*ctx_flags &= ~GSS_C_PROT_READY_FLAG;
-+			*ctx_flags &= ~GSS_C_TRANS_FLAG;
-+		}
-+	}
- 
- 	return (ret);
- }
-@@ -2286,8 +2334,13 @@ spnego_gss_wrap_size_limit(
- 	OM_uint32	*max_input_size)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_wrap_size_limit(minor_status,
--				context_handle,
-+				sc->ctx_handle,
- 				conf_req_flag,
- 				qop_req,
- 				req_output_size,
-@@ -2304,8 +2357,13 @@ spnego_gss_get_mic(
- 		gss_buffer_t message_token)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_get_mic(minor_status,
--		    context_handle,
-+		    sc->ctx_handle,
- 		    qop_req,
- 		    message_buffer,
- 		    message_token);
-@@ -2321,8 +2379,13 @@ spnego_gss_verify_mic(
- 		gss_qop_t *qop_state)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_verify_mic(minor_status,
--			    context_handle,
-+			    sc->ctx_handle,
- 			    msg_buffer,
- 			    token_buffer,
- 			    qop_state);
-@@ -2337,8 +2400,14 @@ spnego_gss_inquire_sec_context_by_oid(
- 		gss_buffer_set_t *data_set)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	/* There are no SPNEGO-specific OIDs for this function. */
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_UNAVAILABLE);
-+
- 	ret = gss_inquire_sec_context_by_oid(minor_status,
--			    context_handle,
-+			    sc->ctx_handle,
- 			    desired_object,
- 			    data_set);
- 	return (ret);
-@@ -2407,8 +2476,15 @@ spnego_gss_set_sec_context_option(
- 		const gss_buffer_t value)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)*context_handle;
-+
-+	/* There are no SPNEGO-specific OIDs for this function, and we cannot
-+	 * construct an empty SPNEGO context with it. */
-+	if (sc == NULL || sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_UNAVAILABLE);
-+
- 	ret = gss_set_sec_context_option(minor_status,
--			    context_handle,
-+			    &sc->ctx_handle,
- 			    desired_object,
- 			    value);
- 	return (ret);
-@@ -2425,8 +2501,13 @@ spnego_gss_wrap_aead(OM_uint32 *minor_status,
- 		     gss_buffer_t output_message_buffer)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_wrap_aead(minor_status,
--			    context_handle,
-+			    sc->ctx_handle,
- 			    conf_req_flag,
- 			    qop_req,
- 			    input_assoc_buffer,
-@@ -2447,8 +2528,13 @@ spnego_gss_unwrap_aead(OM_uint32 *minor_status,
- 		       gss_qop_t *qop_state)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_unwrap_aead(minor_status,
--			      context_handle,
-+			      sc->ctx_handle,
- 			      input_message_buffer,
- 			      input_assoc_buffer,
- 			      output_payload_buffer,
-@@ -2467,8 +2553,13 @@ spnego_gss_wrap_iov(OM_uint32 *minor_status,
- 		    int iov_count)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_wrap_iov(minor_status,
--			   context_handle,
-+			   sc->ctx_handle,
- 			   conf_req_flag,
- 			   qop_req,
- 			   conf_state,
-@@ -2486,8 +2577,13 @@ spnego_gss_unwrap_iov(OM_uint32 *minor_status,
- 		      int iov_count)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_unwrap_iov(minor_status,
--			     context_handle,
-+			     sc->ctx_handle,
- 			     conf_state,
- 			     qop_state,
- 			     iov,
-@@ -2505,8 +2601,13 @@ spnego_gss_wrap_iov_length(OM_uint32 *minor_status,
- 			   int iov_count)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_wrap_iov_length(minor_status,
--				  context_handle,
-+				  sc->ctx_handle,
- 				  conf_req_flag,
- 				  qop_req,
- 				  conf_state,
-@@ -2523,8 +2624,13 @@ spnego_gss_complete_auth_token(
- 		gss_buffer_t input_message_buffer)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_UNAVAILABLE);
-+
- 	ret = gss_complete_auth_token(minor_status,
--				      context_handle,
-+				      sc->ctx_handle,
- 				      input_message_buffer);
- 	return (ret);
- }
-@@ -2776,8 +2882,13 @@ spnego_gss_pseudo_random(OM_uint32 *minor_status,
- 			 gss_buffer_t prf_out)
- {
- 	OM_uint32 ret;
-+	spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context;
-+
-+	if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+		return (GSS_S_NO_CONTEXT);
-+
- 	ret = gss_pseudo_random(minor_status,
--				context,
-+				sc->ctx_handle,
- 				prf_key,
- 				prf_in,
- 				desired_output_len,
-@@ -2918,7 +3029,12 @@ spnego_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
- 		       gss_qop_t qop_req, gss_iov_buffer_desc *iov,
- 		       int iov_count)
- {
--    return gss_get_mic_iov(minor_status, context_handle, qop_req, iov,
-+    spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+    if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+	    return (GSS_S_NO_CONTEXT);
-+
-+    return gss_get_mic_iov(minor_status, sc->ctx_handle, qop_req, iov,
- 			   iov_count);
- }
- 
-@@ -2927,7 +3043,12 @@ spnego_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
- 			  gss_qop_t *qop_state, gss_iov_buffer_desc *iov,
- 			  int iov_count)
- {
--    return gss_verify_mic_iov(minor_status, context_handle, qop_state, iov,
-+    spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+    if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+	    return (GSS_S_NO_CONTEXT);
-+
-+    return gss_verify_mic_iov(minor_status, sc->ctx_handle, qop_state, iov,
- 			      iov_count);
- }
- 
-@@ -2936,7 +3057,12 @@ spnego_gss_get_mic_iov_length(OM_uint32 *minor_status,
- 			      gss_ctx_id_t context_handle, gss_qop_t qop_req,
- 			      gss_iov_buffer_desc *iov, int iov_count)
- {
--    return gss_get_mic_iov_length(minor_status, context_handle, qop_req, iov,
-+    spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle;
-+
-+    if (sc->ctx_handle == GSS_C_NO_CONTEXT)
-+	    return (GSS_S_NO_CONTEXT);
-+
-+    return gss_get_mic_iov_length(minor_status, sc->ctx_handle, qop_req, iov,
- 				  iov_count);
- }
- 
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-2695-pt2.patch b/gnu/packages/patches/mit-krb5-CVE-2015-2695-pt2.patch
deleted file mode 100644
index aa9fcfa0dd..0000000000
--- a/gnu/packages/patches/mit-krb5-CVE-2015-2695-pt2.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-Copied from Debian.
-
-From 18c512ebdcc5cacc777e9dbcc6817f83c301ad93 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 4 Nov 2015 21:29:10 -0500
-Subject: Fix SPNEGO context import
-
-The patches for CVE-2015-2695 did not implement a SPNEGO
-gss_import_sec_context() function, under the erroneous belief than an
-exported SPNEGO context would be tagged with the underlying context
-mechanism.  Implement it now to allow SPNEGO contexts to be
-successfully exported and imported after establishment.
-
-ticket: 8273
-(cherry picked from commit fbb565f913c52eba9bea82f1694aba7a8c90e93d)
-
-Patch-Category: upstream
----
- src/lib/gssapi/spnego/spnego_mech.c | 33 +++++++++++++++++++++++++++------
- 1 file changed, 27 insertions(+), 6 deletions(-)
-
-diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c
-index a1072b0..02284a1 100644
---- a/src/lib/gssapi/spnego/spnego_mech.c
-+++ b/src/lib/gssapi/spnego/spnego_mech.c
-@@ -2256,12 +2256,33 @@ spnego_gss_import_sec_context(
- 	const gss_buffer_t	interprocess_token,
- 	gss_ctx_id_t		*context_handle)
- {
--	/*
--	 * Until we implement partial context exports, there are no SPNEGO
--	 * exported context tokens, only tokens for underlying mechs.  So just
--	 * return an error for now.
--	 */
--	return GSS_S_UNAVAILABLE;
-+	OM_uint32 ret, tmpmin;
-+	gss_ctx_id_t mctx;
-+	spnego_gss_ctx_id_t sc;
-+	int initiate, opened;
-+
-+	ret = gss_import_sec_context(minor_status, interprocess_token, &mctx);
-+	if (ret != GSS_S_COMPLETE)
-+		return ret;
-+
-+	ret = gss_inquire_context(&tmpmin, mctx, NULL, NULL, NULL, NULL, NULL,
-+				  &initiate, &opened);
-+	if (ret != GSS_S_COMPLETE || !opened) {
-+		/* We don't currently support importing partially established
-+		 * contexts. */
-+		(void) gss_delete_sec_context(&tmpmin, &mctx, GSS_C_NO_BUFFER);
-+		return GSS_S_FAILURE;
-+	}
-+
-+	sc = create_spnego_ctx(initiate);
-+	if (sc == NULL) {
-+		(void) gss_delete_sec_context(&tmpmin, &mctx, GSS_C_NO_BUFFER);
-+		return GSS_S_FAILURE;
-+	}
-+	sc->ctx_handle = mctx;
-+	sc->opened = 1;
-+	*context_handle = (gss_ctx_id_t)sc;
-+	return GSS_S_COMPLETE;
- }
- #endif /* LEAN_CLIENT */
- 
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-2696.patch b/gnu/packages/patches/mit-krb5-CVE-2015-2696.patch
deleted file mode 100644
index 7b4b1d71ab..0000000000
--- a/gnu/packages/patches/mit-krb5-CVE-2015-2696.patch
+++ /dev/null
@@ -1,736 +0,0 @@
-Copied from Debian.
-
-From ebea85358bc72ec20c53130d83acb93f95853b76 Mon Sep 17 00:00:00 2001
-From: Nicolas Williams <nico@twosigma.com>
-Date: Mon, 14 Sep 2015 12:28:36 -0400
-Subject: Fix IAKERB context aliasing bugs [CVE-2015-2696]
-
-The IAKERB mechanism currently replaces its context handle with the
-krb5 mechanism handle upon establishment, under the assumption that
-most GSS functions are only called after context establishment.  This
-assumption is incorrect, and can lead to aliasing violations for some
-programs.  Maintain the IAKERB context structure after context
-establishment and add new IAKERB entry points to refer to it with that
-type.  Add initiate and established flags to the IAKERB context
-structure for use in gss_inquire_context() prior to context
-establishment.
-
-CVE-2015-2696:
-
-In MIT krb5 1.9 and later, applications which call
-gss_inquire_context() on a partially-established IAKERB context can
-cause the GSS-API library to read from a pointer using the wrong type,
-generally causing a process crash.  Java server applications using the
-native JGSS provider are vulnerable to this bug.  A carefully crafted
-IAKERB packet might allow the gss_inquire_context() call to succeed
-with attacker-determined results, but applications should not make
-access control decisions based on gss_inquire_context() results prior
-to context establishment.
-
-    CVSSv2 Vector: AV:N/AC:M/Au:N/C:N/I:N/A:C/E:POC/RL:OF/RC:C
-
-[ghudson@mit.edu: several bugfixes, style changes, and edge-case
-behavior changes; commit message and CVE description]
-
-ticket: 8244
-target_version: 1.14
-tags: pullup
-
-(cherry picked from commit e04f0283516e80d2f93366e0d479d13c9b5c8c2a)
-Patch-Category: upstream
----
- src/lib/gssapi/krb5/gssapiP_krb5.h | 114 ++++++++++++
- src/lib/gssapi/krb5/gssapi_krb5.c  | 105 +++++++++--
- src/lib/gssapi/krb5/iakerb.c       | 351 +++++++++++++++++++++++++++++++++----
- 3 files changed, 529 insertions(+), 41 deletions(-)
-
-diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
-index a0e8625..05dc321 100644
---- a/src/lib/gssapi/krb5/gssapiP_krb5.h
-+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
-@@ -620,6 +620,21 @@ OM_uint32 KRB5_CALLCONV krb5_gss_accept_sec_context_ext
- );
- #endif /* LEAN_CLIENT */
- 
-+OM_uint32 KRB5_CALLCONV krb5_gss_inquire_sec_context_by_oid
-+(OM_uint32*,       /* minor_status */
-+ const gss_ctx_id_t,
-+ /* context_handle */
-+ const gss_OID,    /* desired_object */
-+ gss_buffer_set_t* /* data_set */
-+);
-+
-+OM_uint32 KRB5_CALLCONV krb5_gss_set_sec_context_option
-+(OM_uint32*,       /* minor_status */
-+ gss_ctx_id_t*,    /* context_handle */
-+ const gss_OID,    /* desired_object */
-+ const gss_buffer_t/* value */
-+);
-+
- OM_uint32 KRB5_CALLCONV krb5_gss_process_context_token
- (OM_uint32*,       /* minor_status */
-  gss_ctx_id_t,     /* context_handle */
-@@ -1301,6 +1316,105 @@ OM_uint32 KRB5_CALLCONV
- krb5_gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token,
-                      gss_cred_id_t *cred_handle);
- 
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_process_context_token(OM_uint32 *minor_status,
-+                                 const gss_ctx_id_t context_handle,
-+                                 const gss_buffer_t token_buffer);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                        OM_uint32 *time_rec);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_inquire_context(OM_uint32 *minor_status,
-+                           gss_ctx_id_t context_handle, gss_name_t *src_name,
-+                           gss_name_t *targ_name, OM_uint32 *lifetime_rec,
-+                           gss_OID *mech_type, OM_uint32 *ctx_flags,
-+                           int *locally_initiated, int *opened);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_get_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                   gss_qop_t qop_req, gss_buffer_t message_buffer,
-+                   gss_buffer_t message_token);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                       gss_qop_t qop_req, gss_iov_buffer_desc *iov,
-+                       int iov_count);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_get_mic_iov_length(OM_uint32 *minor_status,
-+                              gss_ctx_id_t context_handle, gss_qop_t qop_req,
-+                              gss_iov_buffer_desc *iov, int iov_count);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_verify_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                      gss_buffer_t msg_buffer, gss_buffer_t token_buffer,
-+                      gss_qop_t *qop_state);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                          gss_qop_t *qop_state, gss_iov_buffer_desc *iov,
-+                          int iov_count);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                int conf_req_flag, gss_qop_t qop_req,
-+                gss_buffer_t input_message_buffer, int *conf_state,
-+                gss_buffer_t output_message_buffer);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                    int conf_req_flag, gss_qop_t qop_req, int *conf_state,
-+                    gss_iov_buffer_desc *iov, int iov_count);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap_iov_length(OM_uint32 *minor_status,
-+                           gss_ctx_id_t context_handle, int conf_req_flag,
-+                           gss_qop_t qop_req, int *conf_state,
-+                           gss_iov_buffer_desc *iov, int iov_count);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_unwrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                  gss_buffer_t input_message_buffer,
-+                  gss_buffer_t output_message_buffer, int *conf_state,
-+                  gss_qop_t *qop_state);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                      int *conf_state, gss_qop_t *qop_state,
-+                      gss_iov_buffer_desc *iov, int iov_count);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap_size_limit(OM_uint32 *minor_status,
-+                           gss_ctx_id_t context_handle, int conf_req_flag,
-+                           gss_qop_t qop_req, OM_uint32 req_output_size,
-+                           OM_uint32 *max_input_size);
-+
-+#ifndef LEAN_CLIENT
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_export_sec_context(OM_uint32 *minor_status,
-+                              gss_ctx_id_t *context_handle,
-+                              gss_buffer_t interprocess_token);
-+#endif /* LEAN_CLIENT */
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
-+                                      const gss_ctx_id_t context_handle,
-+                                      const gss_OID desired_object,
-+                                      gss_buffer_set_t *data_set);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_set_sec_context_option(OM_uint32 *minor_status,
-+                                  gss_ctx_id_t *context_handle,
-+                                  const gss_OID desired_object,
-+                                  const gss_buffer_t value);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                         int prf_key, const gss_buffer_t prf_in,
-+                         ssize_t desired_output_len, gss_buffer_t prf_out);
-+
- /* Magic string to identify exported krb5 GSS credentials.  Increment this if
-  * the format changes. */
- #define CRED_EXPORT_MAGIC "K5C1"
-diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
-index 77b7fff..9a23656 100644
---- a/src/lib/gssapi/krb5/gssapi_krb5.c
-+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
-@@ -345,7 +345,7 @@ static struct {
-     }
- };
- 
--static OM_uint32 KRB5_CALLCONV
-+OM_uint32 KRB5_CALLCONV
- krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
-                                      const gss_ctx_id_t context_handle,
-                                      const gss_OID desired_object,
-@@ -459,7 +459,7 @@ static struct {
- };
- #endif
- 
--static OM_uint32 KRB5_CALLCONV
-+OM_uint32 KRB5_CALLCONV
- krb5_gss_set_sec_context_option (OM_uint32 *minor_status,
-                                  gss_ctx_id_t *context_handle,
-                                  const gss_OID desired_object,
-@@ -904,20 +904,103 @@ static struct gss_config krb5_mechanism = {
-     krb5_gss_get_mic_iov_length,
- };
- 
-+/* Functions which use security contexts or acquire creds are IAKERB-specific;
-+ * other functions can borrow from the krb5 mech. */
-+static struct gss_config iakerb_mechanism = {
-+    { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
-+    NULL,
-+    iakerb_gss_acquire_cred,
-+    krb5_gss_release_cred,
-+    iakerb_gss_init_sec_context,
-+#ifdef LEAN_CLIENT
-+    NULL,
-+#else
-+    iakerb_gss_accept_sec_context,
-+#endif
-+    iakerb_gss_process_context_token,
-+    iakerb_gss_delete_sec_context,
-+    iakerb_gss_context_time,
-+    iakerb_gss_get_mic,
-+    iakerb_gss_verify_mic,
-+#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE)
-+    NULL,
-+#else
-+    iakerb_gss_wrap,
-+#endif
-+#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE)
-+    NULL,
-+#else
-+    iakerb_gss_unwrap,
-+#endif
-+    krb5_gss_display_status,
-+    krb5_gss_indicate_mechs,
-+    krb5_gss_compare_name,
-+    krb5_gss_display_name,
-+    krb5_gss_import_name,
-+    krb5_gss_release_name,
-+    krb5_gss_inquire_cred,
-+    NULL,                /* add_cred */
-+#ifdef LEAN_CLIENT
-+    NULL,
-+    NULL,
-+#else
-+    iakerb_gss_export_sec_context,
-+    NULL,
-+#endif
-+    krb5_gss_inquire_cred_by_mech,
-+    krb5_gss_inquire_names_for_mech,
-+    iakerb_gss_inquire_context,
-+    krb5_gss_internal_release_oid,
-+    iakerb_gss_wrap_size_limit,
-+    krb5_gss_localname,
-+    krb5_gss_authorize_localname,
-+    krb5_gss_export_name,
-+    krb5_gss_duplicate_name,
-+    krb5_gss_store_cred,
-+    iakerb_gss_inquire_sec_context_by_oid,
-+    krb5_gss_inquire_cred_by_oid,
-+    iakerb_gss_set_sec_context_option,
-+    krb5_gssspi_set_cred_option,
-+    krb5_gssspi_mech_invoke,
-+    NULL,                /* wrap_aead */
-+    NULL,                /* unwrap_aead */
-+    iakerb_gss_wrap_iov,
-+    iakerb_gss_unwrap_iov,
-+    iakerb_gss_wrap_iov_length,
-+    NULL,               /* complete_auth_token */
-+    NULL,               /* acquire_cred_impersonate_name */
-+    NULL,               /* add_cred_impersonate_name */
-+    NULL,               /* display_name_ext */
-+    krb5_gss_inquire_name,
-+    krb5_gss_get_name_attribute,
-+    krb5_gss_set_name_attribute,
-+    krb5_gss_delete_name_attribute,
-+    krb5_gss_export_name_composite,
-+    krb5_gss_map_name_to_any,
-+    krb5_gss_release_any_name_mapping,
-+    iakerb_gss_pseudo_random,
-+    NULL,               /* set_neg_mechs */
-+    krb5_gss_inquire_saslname_for_mech,
-+    krb5_gss_inquire_mech_for_saslname,
-+    krb5_gss_inquire_attrs_for_mech,
-+    krb5_gss_acquire_cred_from,
-+    krb5_gss_store_cred_into,
-+    iakerb_gss_acquire_cred_with_password,
-+    krb5_gss_export_cred,
-+    krb5_gss_import_cred,
-+    NULL,               /* import_sec_context_by_mech */
-+    NULL,               /* import_name_by_mech */
-+    NULL,               /* import_cred_by_mech */
-+    iakerb_gss_get_mic_iov,
-+    iakerb_gss_verify_mic_iov,
-+    iakerb_gss_get_mic_iov_length,
-+};
-+
- #ifdef _GSS_STATIC_LINK
- #include "mglueP.h"
- static int gss_iakerbmechglue_init(void)
- {
-     struct gss_mech_config mech_iakerb;
--    struct gss_config iakerb_mechanism = krb5_mechanism;
--
--    /* IAKERB mechanism mirrors krb5, but with different context SPIs */
--    iakerb_mechanism.gss_accept_sec_context = iakerb_gss_accept_sec_context;
--    iakerb_mechanism.gss_init_sec_context   = iakerb_gss_init_sec_context;
--    iakerb_mechanism.gss_delete_sec_context = iakerb_gss_delete_sec_context;
--    iakerb_mechanism.gss_acquire_cred       = iakerb_gss_acquire_cred;
--    iakerb_mechanism.gssspi_acquire_cred_with_password
--                                    = iakerb_gss_acquire_cred_with_password;
- 
-     memset(&mech_iakerb, 0, sizeof(mech_iakerb));
-     mech_iakerb.mech = &iakerb_mechanism;
-diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
-index f30de32..4662bd9 100644
---- a/src/lib/gssapi/krb5/iakerb.c
-+++ b/src/lib/gssapi/krb5/iakerb.c
-@@ -47,6 +47,8 @@ struct _iakerb_ctx_id_rec {
-     gss_ctx_id_t gssc;
-     krb5_data conv;                     /* conversation for checksumming */
-     unsigned int count;                 /* number of round trips */
-+    int initiate;
-+    int established;
-     krb5_get_init_creds_opt *gic_opts;
- };
- 
-@@ -695,7 +697,7 @@ cleanup:
-  * Allocate and initialise an IAKERB context
-  */
- static krb5_error_code
--iakerb_alloc_context(iakerb_ctx_id_t *pctx)
-+iakerb_alloc_context(iakerb_ctx_id_t *pctx, int initiate)
- {
-     iakerb_ctx_id_t ctx;
-     krb5_error_code code;
-@@ -709,6 +711,8 @@ iakerb_alloc_context(iakerb_ctx_id_t *pctx)
-     ctx->magic = KG_IAKERB_CONTEXT;
-     ctx->state = IAKERB_AS_REQ;
-     ctx->count = 0;
-+    ctx->initiate = initiate;
-+    ctx->established = 0;
- 
-     code = krb5_gss_init_context(&ctx->k5c);
-     if (code != 0)
-@@ -732,7 +736,7 @@ iakerb_gss_delete_sec_context(OM_uint32 *minor_status,
-                               gss_ctx_id_t *context_handle,
-                               gss_buffer_t output_token)
- {
--    OM_uint32 major_status = GSS_S_COMPLETE;
-+    iakerb_ctx_id_t iakerb_ctx = (iakerb_ctx_id_t)*context_handle;
- 
-     if (output_token != GSS_C_NO_BUFFER) {
-         output_token->length = 0;
-@@ -740,23 +744,10 @@ iakerb_gss_delete_sec_context(OM_uint32 *minor_status,
-     }
- 
-     *minor_status = 0;
-+    *context_handle = GSS_C_NO_CONTEXT;
-+    iakerb_release_context(iakerb_ctx);
- 
--    if (*context_handle != GSS_C_NO_CONTEXT) {
--        iakerb_ctx_id_t iakerb_ctx = (iakerb_ctx_id_t)*context_handle;
--
--        if (iakerb_ctx->magic == KG_IAKERB_CONTEXT) {
--            iakerb_release_context(iakerb_ctx);
--            *context_handle = GSS_C_NO_CONTEXT;
--        } else {
--            assert(iakerb_ctx->magic == KG_CONTEXT);
--
--            major_status = krb5_gss_delete_sec_context(minor_status,
--                                                       context_handle,
--                                                       output_token);
--        }
--    }
--
--    return major_status;
-+    return GSS_S_COMPLETE;
- }
- 
- static krb5_boolean
-@@ -802,7 +793,7 @@ iakerb_gss_accept_sec_context(OM_uint32 *minor_status,
-     int initialContextToken = (*context_handle == GSS_C_NO_CONTEXT);
- 
-     if (initialContextToken) {
--        code = iakerb_alloc_context(&ctx);
-+        code = iakerb_alloc_context(&ctx, 0);
-         if (code != 0)
-             goto cleanup;
- 
-@@ -854,11 +845,8 @@ iakerb_gss_accept_sec_context(OM_uint32 *minor_status,
-                                                        time_rec,
-                                                        delegated_cred_handle,
-                                                        &exts);
--        if (major_status == GSS_S_COMPLETE) {
--            *context_handle = ctx->gssc;
--            ctx->gssc = NULL;
--            iakerb_release_context(ctx);
--        }
-+        if (major_status == GSS_S_COMPLETE)
-+            ctx->established = 1;
-         if (mech_type != NULL)
-             *mech_type = (gss_OID)gss_mech_krb5;
-     }
-@@ -897,7 +885,7 @@ iakerb_gss_init_sec_context(OM_uint32 *minor_status,
-     int initialContextToken = (*context_handle == GSS_C_NO_CONTEXT);
- 
-     if (initialContextToken) {
--        code = iakerb_alloc_context(&ctx);
-+        code = iakerb_alloc_context(&ctx, 1);
-         if (code != 0) {
-             *minor_status = code;
-             goto cleanup;
-@@ -983,11 +971,8 @@ iakerb_gss_init_sec_context(OM_uint32 *minor_status,
-                                                      ret_flags,
-                                                      time_rec,
-                                                      &exts);
--        if (major_status == GSS_S_COMPLETE) {
--            *context_handle = ctx->gssc;
--            ctx->gssc = GSS_C_NO_CONTEXT;
--            iakerb_release_context(ctx);
--        }
-+        if (major_status == GSS_S_COMPLETE)
-+            ctx->established = 1;
-         if (actual_mech_type != NULL)
-             *actual_mech_type = (gss_OID)gss_mech_krb5;
-     } else {
-@@ -1010,3 +995,309 @@ cleanup:
- 
-     return major_status;
- }
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_unwrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                  gss_buffer_t input_message_buffer,
-+                  gss_buffer_t output_message_buffer, int *conf_state,
-+                  gss_qop_t *qop_state)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_unwrap(minor_status, ctx->gssc, input_message_buffer,
-+                           output_message_buffer, conf_state, qop_state);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                int conf_req_flag, gss_qop_t qop_req,
-+                gss_buffer_t input_message_buffer, int *conf_state,
-+                gss_buffer_t output_message_buffer)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_wrap(minor_status, ctx->gssc, conf_req_flag, qop_req,
-+                         input_message_buffer, conf_state,
-+                         output_message_buffer);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_process_context_token(OM_uint32 *minor_status,
-+                                 const gss_ctx_id_t context_handle,
-+                                 const gss_buffer_t token_buffer)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_DEFECTIVE_TOKEN;
-+
-+    return krb5_gss_process_context_token(minor_status, ctx->gssc,
-+                                          token_buffer);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                        OM_uint32 *time_rec)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_context_time(minor_status, ctx->gssc, time_rec);
-+}
-+
-+#ifndef LEAN_CLIENT
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_export_sec_context(OM_uint32 *minor_status,
-+                              gss_ctx_id_t *context_handle,
-+                              gss_buffer_t interprocess_token)
-+{
-+    OM_uint32 maj;
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    /* We don't currently support exporting partially established contexts. */
-+    if (!ctx->established)
-+        return GSS_S_UNAVAILABLE;
-+
-+    maj = krb5_gss_export_sec_context(minor_status, &ctx->gssc,
-+                                      interprocess_token);
-+    if (ctx->gssc == GSS_C_NO_CONTEXT) {
-+        iakerb_release_context(ctx);
-+        *context_handle = GSS_C_NO_CONTEXT;
-+    }
-+    return maj;
-+}
-+
-+/*
-+ * Until we implement partial context exports, there are no SPNEGO exported
-+ * context tokens, only tokens for the underlying krb5 context.  So we do not
-+ * need to implement an iakerb_gss_import_sec_context() yet; it would be
-+ * unreachable except via a manually constructed token.
-+ */
-+
-+#endif /* LEAN_CLIENT */
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_inquire_context(OM_uint32 *minor_status,
-+                           gss_ctx_id_t context_handle, gss_name_t *src_name,
-+                           gss_name_t *targ_name, OM_uint32 *lifetime_rec,
-+                           gss_OID *mech_type, OM_uint32 *ctx_flags,
-+                           int *initiate, int *opened)
-+{
-+    OM_uint32 ret;
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (src_name != NULL)
-+        *src_name = GSS_C_NO_NAME;
-+    if (targ_name != NULL)
-+        *targ_name = GSS_C_NO_NAME;
-+    if (lifetime_rec != NULL)
-+        *lifetime_rec = 0;
-+    if (mech_type != NULL)
-+        *mech_type = (gss_OID)gss_mech_iakerb;
-+    if (ctx_flags != NULL)
-+        *ctx_flags = 0;
-+    if (initiate != NULL)
-+        *initiate = ctx->initiate;
-+    if (opened != NULL)
-+        *opened = ctx->established;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_COMPLETE;
-+
-+    ret = krb5_gss_inquire_context(minor_status, ctx->gssc, src_name,
-+                                   targ_name, lifetime_rec, mech_type,
-+                                   ctx_flags, initiate, opened);
-+
-+    if (!ctx->established) {
-+        /* Report IAKERB as the mech OID until the context is established. */
-+        if (mech_type != NULL)
-+            *mech_type = (gss_OID)gss_mech_iakerb;
-+
-+        /* We don't support exporting partially-established contexts. */
-+        if (ctx_flags != NULL)
-+            *ctx_flags &= ~GSS_C_TRANS_FLAG;
-+    }
-+
-+    return ret;
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap_size_limit(OM_uint32 *minor_status,
-+                           gss_ctx_id_t context_handle, int conf_req_flag,
-+                           gss_qop_t qop_req, OM_uint32 req_output_size,
-+                           OM_uint32 *max_input_size)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_wrap_size_limit(minor_status, ctx->gssc, conf_req_flag,
-+                                    qop_req, req_output_size, max_input_size);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_get_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                   gss_qop_t qop_req, gss_buffer_t message_buffer,
-+                   gss_buffer_t message_token)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_get_mic(minor_status, ctx->gssc, qop_req, message_buffer,
-+                            message_token);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_verify_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                      gss_buffer_t msg_buffer, gss_buffer_t token_buffer,
-+                      gss_qop_t *qop_state)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_verify_mic(minor_status, ctx->gssc, msg_buffer,
-+                               token_buffer, qop_state);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_inquire_sec_context_by_oid(OM_uint32 *minor_status,
-+                                      const gss_ctx_id_t context_handle,
-+                                      const gss_OID desired_object,
-+                                      gss_buffer_set_t *data_set)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_UNAVAILABLE;
-+
-+    return krb5_gss_inquire_sec_context_by_oid(minor_status, ctx->gssc,
-+                                               desired_object, data_set);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_set_sec_context_option(OM_uint32 *minor_status,
-+                                  gss_ctx_id_t *context_handle,
-+                                  const gss_OID desired_object,
-+                                  const gss_buffer_t value)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)*context_handle;
-+
-+    if (ctx == NULL || ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_UNAVAILABLE;
-+
-+    return krb5_gss_set_sec_context_option(minor_status, &ctx->gssc,
-+                                           desired_object, value);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                    int conf_req_flag, gss_qop_t qop_req, int *conf_state,
-+                    gss_iov_buffer_desc *iov, int iov_count)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_wrap_iov(minor_status, ctx->gssc, conf_req_flag, qop_req,
-+                             conf_state, iov, iov_count);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                      int *conf_state, gss_qop_t *qop_state,
-+                      gss_iov_buffer_desc *iov, int iov_count)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_unwrap_iov(minor_status, ctx->gssc, conf_state, qop_state,
-+                               iov, iov_count);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_wrap_iov_length(OM_uint32 *minor_status,
-+                           gss_ctx_id_t context_handle, int conf_req_flag,
-+                           gss_qop_t qop_req, int *conf_state,
-+                           gss_iov_buffer_desc *iov, int iov_count)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_wrap_iov_length(minor_status, ctx->gssc, conf_req_flag,
-+                                    qop_req, conf_state, iov, iov_count);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                         int prf_key, const gss_buffer_t prf_in,
-+                         ssize_t desired_output_len, gss_buffer_t prf_out)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_pseudo_random(minor_status, ctx->gssc, prf_key, prf_in,
-+                                  desired_output_len, prf_out);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                       gss_qop_t qop_req, gss_iov_buffer_desc *iov,
-+                       int iov_count)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_get_mic_iov(minor_status, ctx->gssc, qop_req, iov,
-+                                iov_count);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle,
-+                          gss_qop_t *qop_state, gss_iov_buffer_desc *iov,
-+                          int iov_count)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_verify_mic_iov(minor_status, ctx->gssc, qop_state, iov,
-+                                   iov_count);
-+}
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_get_mic_iov_length(OM_uint32 *minor_status,
-+                              gss_ctx_id_t context_handle, gss_qop_t qop_req,
-+                              gss_iov_buffer_desc *iov, int iov_count)
-+{
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+
-+    if (ctx->gssc == GSS_C_NO_CONTEXT)
-+        return GSS_S_NO_CONTEXT;
-+
-+    return krb5_gss_get_mic_iov_length(minor_status, ctx->gssc, qop_req, iov,
-+                                       iov_count);
-+}
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-2697.patch b/gnu/packages/patches/mit-krb5-CVE-2015-2697.patch
deleted file mode 100644
index f65ce39623..0000000000
--- a/gnu/packages/patches/mit-krb5-CVE-2015-2697.patch
+++ /dev/null
@@ -1,55 +0,0 @@
-Copied from Debian.
-
-From fcafb522a0509bfd6f4f6b57e4a1e93c0092eeb0 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Fri, 25 Sep 2015 12:51:47 -0400
-Subject: Fix build_principal memory bug [CVE-2015-2697]
-
-In build_principal_va(), use k5memdup0() instead of strdup() to make a
-copy of the realm, to ensure that we allocate the correct number of
-bytes and do not read past the end of the input string.  This bug
-affects krb5_build_principal(), krb5_build_principal_va(), and
-krb5_build_principal_alloc_va().  krb5_build_principal_ext() is not
-affected.
-
-CVE-2015-2697:
-
-In MIT krb5 1.7 and later, an authenticated attacker may be able to
-cause a KDC to crash using a TGS request with a large realm field
-beginning with a null byte.  If the KDC attempts to find a referral to
-answer the request, it constructs a principal name for lookup using
-krb5_build_principal() with the requested realm.  Due to a bug in this
-function, the null byte causes only one byte be allocated for the
-realm field of the constructed principal, far less than its length.
-Subsequent operations on the lookup principal may cause a read beyond
-the end of the mapped memory region, causing the KDC process to crash.
-
-CVSSv2: AV:N/AC:L/Au:S/C:N/I:N/A:C/E:POC/RL:OF/RC:C
-
-ticket: 8252 (new)
-target_version: 1.14
-tags: pullup
-
-(cherry picked from commit f0c094a1b745d91ef2f9a4eae2149aac026a5789)
-Patch-Category: upstream
----
- src/lib/krb5/krb/bld_princ.c | 6 ++----
- 1 file changed, 2 insertions(+), 4 deletions(-)
-
-diff --git a/src/lib/krb5/krb/bld_princ.c b/src/lib/krb5/krb/bld_princ.c
-index ab6fed8..8604268 100644
---- a/src/lib/krb5/krb/bld_princ.c
-+++ b/src/lib/krb5/krb/bld_princ.c
-@@ -40,10 +40,8 @@ build_principal_va(krb5_context context, krb5_principal princ,
-     data = malloc(size * sizeof(krb5_data));
-     if (!data) { retval = ENOMEM; }
- 
--    if (!retval) {
--        r = strdup(realm);
--        if (!r) { retval = ENOMEM; }
--    }
-+    if (!retval)
-+        r = k5memdup0(realm, rlen, &retval);
- 
-     while (!retval && (component = va_arg(ap, char *))) {
-         if (count == size) {
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-2698-pt1.patch b/gnu/packages/patches/mit-krb5-CVE-2015-2698-pt1.patch
deleted file mode 100644
index 67545e4c16..0000000000
--- a/gnu/packages/patches/mit-krb5-CVE-2015-2698-pt1.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-Copied from Debian.
-
-From 1a8bdc6d81dcd7dd8a4d42e8de6d2cacf1dd4408 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Tue, 27 Oct 2015 00:44:24 -0400
-Subject: Fix two IAKERB comments
-
-The comment explaining why there is no iakerb_gss_import_sec_context()
-erroneously referenced SPNEGO instead of IAKERB (noticed by Ben
-Kaduk).  The comment above iakerb_gss_delete_sec_context() is out of
-date after the last commit.
-
-(cherry picked from commit 92d6dd045dfc06cc03d20b327a6ee7a71e6bc24d)
-
-Patch-Category: upstream
----
- src/lib/gssapi/krb5/iakerb.c | 6 +-----
- 1 file changed, 1 insertion(+), 5 deletions(-)
-
-diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
-index 4662bd9..e25862d 100644
---- a/src/lib/gssapi/krb5/iakerb.c
-+++ b/src/lib/gssapi/krb5/iakerb.c
-@@ -727,10 +727,6 @@ cleanup:
-     return code;
- }
- 
--/*
-- * Delete an IAKERB context. This can also accept Kerberos context
-- * handles. The heuristic is similar to SPNEGO's delete_sec_context.
-- */
- OM_uint32 KRB5_CALLCONV
- iakerb_gss_delete_sec_context(OM_uint32 *minor_status,
-                               gss_ctx_id_t *context_handle,
-@@ -1077,7 +1073,7 @@ iakerb_gss_export_sec_context(OM_uint32 *minor_status,
- }
- 
- /*
-- * Until we implement partial context exports, there are no SPNEGO exported
-+ * Until we implement partial context exports, there are no IAKERB exported
-  * context tokens, only tokens for the underlying krb5 context.  So we do not
-  * need to implement an iakerb_gss_import_sec_context() yet; it would be
-  * unreachable except via a manually constructed token.
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-2698-pt2.patch b/gnu/packages/patches/mit-krb5-CVE-2015-2698-pt2.patch
deleted file mode 100644
index 8725cd4eed..0000000000
--- a/gnu/packages/patches/mit-krb5-CVE-2015-2698-pt2.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-Copied from Debian.
-
-From 4b330d5be1f8048be4d079ac3cb38d60c0e99e69 Mon Sep 17 00:00:00 2001
-From: Greg Hudson <ghudson@mit.edu>
-Date: Wed, 4 Nov 2015 21:28:28 -0500
-Subject: Fix IAKERB context export/import [CVE-2015-2698]
-
-The patches for CVE-2015-2696 contained a regression in the newly
-added IAKERB iakerb_gss_export_sec_context() function, which could
-cause it to corrupt memory.  Fix the regression by properly
-dereferencing the context_handle pointer before casting it.
-
-Also, the patches did not implement an IAKERB gss_import_sec_context()
-function, under the erroneous belief than an exported IAKERB context
-would be tagged as a krb5 context.  Implement it now to allow IAKERB
-contexts to be successfully exported and imported after establishment.
-
-CVE-2015-2698:
-
-In any MIT krb5 release with the patches for CVE-2015-2696 applied, an
-application which calls gss_export_sec_context() may experience memory
-corruption if the context was established using the IAKERB mechanism.
-Historically, some vulnerabilities of this nature can be translated
-into remote code execution, though the necessary exploits must be
-tailored to the individual application and are usually quite
-complicated.
-
-    CVSSv2 Vector: AV:N/AC:H/Au:S/C:C/I:C/A:C/E:POC/RL:OF/RC:C
-
-ticket: 8273 (new)
-target_version: 1.14
-tags: pullup
-
-(cherry picked from commit d8b31c874c7d1039be7649362ef11c89f4e14c27)
-
-Patch-Category: upstream
----
- src/lib/gssapi/krb5/gssapiP_krb5.h |  5 +++++
- src/lib/gssapi/krb5/gssapi_krb5.c  |  2 +-
- src/lib/gssapi/krb5/iakerb.c       | 42 +++++++++++++++++++++++++++++++-------
- 3 files changed, 41 insertions(+), 8 deletions(-)
-
-diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
-index 05dc321..ac53662 100644
---- a/src/lib/gssapi/krb5/gssapiP_krb5.h
-+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
-@@ -1396,6 +1396,11 @@ OM_uint32 KRB5_CALLCONV
- iakerb_gss_export_sec_context(OM_uint32 *minor_status,
-                               gss_ctx_id_t *context_handle,
-                               gss_buffer_t interprocess_token);
-+
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_import_sec_context(OM_uint32 *minor_status,
-+                              const gss_buffer_t interprocess_token,
-+                              gss_ctx_id_t *context_handle);
- #endif /* LEAN_CLIENT */
- 
- OM_uint32 KRB5_CALLCONV
-diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
-index 9a23656..d7ba279 100644
---- a/src/lib/gssapi/krb5/gssapi_krb5.c
-+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
-@@ -945,7 +945,7 @@ static struct gss_config iakerb_mechanism = {
-     NULL,
- #else
-     iakerb_gss_export_sec_context,
--    NULL,
-+    iakerb_gss_import_sec_context,
- #endif
-     krb5_gss_inquire_cred_by_mech,
-     krb5_gss_inquire_names_for_mech,
-diff --git a/src/lib/gssapi/krb5/iakerb.c b/src/lib/gssapi/krb5/iakerb.c
-index e25862d..32a341e 100644
---- a/src/lib/gssapi/krb5/iakerb.c
-+++ b/src/lib/gssapi/krb5/iakerb.c
-@@ -1057,7 +1057,7 @@ iakerb_gss_export_sec_context(OM_uint32 *minor_status,
-                               gss_buffer_t interprocess_token)
- {
-     OM_uint32 maj;
--    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle;
-+    iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)*context_handle;
- 
-     /* We don't currently support exporting partially established contexts. */
-     if (!ctx->established)
-@@ -1072,13 +1072,41 @@ iakerb_gss_export_sec_context(OM_uint32 *minor_status,
-     return maj;
- }
- 
--/*
-- * Until we implement partial context exports, there are no IAKERB exported
-- * context tokens, only tokens for the underlying krb5 context.  So we do not
-- * need to implement an iakerb_gss_import_sec_context() yet; it would be
-- * unreachable except via a manually constructed token.
-- */
-+OM_uint32 KRB5_CALLCONV
-+iakerb_gss_import_sec_context(OM_uint32 *minor_status,
-+                              gss_buffer_t interprocess_token,
-+                              gss_ctx_id_t *context_handle)
-+{
-+    OM_uint32 maj, tmpmin;
-+    krb5_error_code code;
-+    gss_ctx_id_t gssc;
-+    krb5_gss_ctx_id_t kctx;
-+    iakerb_ctx_id_t ctx;
-+
-+    maj = krb5_gss_import_sec_context(minor_status, interprocess_token, &gssc);
-+    if (maj != GSS_S_COMPLETE)
-+        return maj;
-+    kctx = (krb5_gss_ctx_id_t)gssc;
-+
-+    if (!kctx->established) {
-+        /* We don't currently support importing partially established
-+         * contexts. */
-+        krb5_gss_delete_sec_context(&tmpmin, &gssc, GSS_C_NO_BUFFER);
-+        return GSS_S_FAILURE;
-+    }
- 
-+    code = iakerb_alloc_context(&ctx, kctx->initiate);
-+    if (code != 0) {
-+        krb5_gss_delete_sec_context(&tmpmin, &gssc, GSS_C_NO_BUFFER);
-+        *minor_status = code;
-+        return GSS_S_FAILURE;
-+    }
-+
-+    ctx->gssc = gssc;
-+    ctx->established = 1;
-+    *context_handle = (gss_ctx_id_t)ctx;
-+    return GSS_S_COMPLETE;
-+}
- #endif /* LEAN_CLIENT */
- 
- OM_uint32 KRB5_CALLCONV
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-8629.patch b/gnu/packages/patches/mit-krb5-CVE-2015-8629.patch
new file mode 100644
index 0000000000..a296d8cb1b
--- /dev/null
+++ b/gnu/packages/patches/mit-krb5-CVE-2015-8629.patch
@@ -0,0 +1,51 @@
+Copied from Fedora.
+http://pkgs.fedoraproject.org/cgit/rpms/krb5.git/tree/krb5-CVE-2015-8629.patch?h=f22
+
+From df17a1224a3406f57477bcd372c61e04c0e5a5bb Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 8 Jan 2016 12:45:25 -0500
+Subject: [PATCH 1/3] Verify decoded kadmin C strings [CVE-2015-8629]
+
+In xdr_nullstring(), check that the decoded string is terminated with
+a zero byte and does not contain any internal zero bytes.
+
+CVE-2015-8629:
+
+In all versions of MIT krb5, an authenticated attacker can cause
+kadmind to read beyond the end of allocated memory by sending a string
+without a terminating zero byte.  Information leakage may be possible
+for an attacker with permission to modify the database.
+
+    CVSSv2 Vector: AV:N/AC:H/Au:S/C:P/I:N/A:N/E:POC/RL:OF/RC:C
+
+ticket: 8341 (new)
+target_version: 1.14-next
+target_version: 1.13-next
+tags: pullup
+---
+ src/lib/kadm5/kadm_rpc_xdr.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c
+index 2bef858..ba67084 100644
+--- a/src/lib/kadm5/kadm_rpc_xdr.c
++++ b/src/lib/kadm5/kadm_rpc_xdr.c
+@@ -64,7 +64,14 @@ bool_t xdr_nullstring(XDR *xdrs, char **objp)
+ 		    return FALSE;
+ 	       }
+ 	  }
+-	  return (xdr_opaque(xdrs, *objp, size));
++	  if (!xdr_opaque(xdrs, *objp, size))
++		  return FALSE;
++	  /* Check that the unmarshalled bytes are a C string. */
++	  if ((*objp)[size - 1] != '\0')
++		  return FALSE;
++	  if (memchr(*objp, '\0', size - 1) != NULL)
++		  return FALSE;
++	  return TRUE;
+ 
+      case XDR_ENCODE:
+ 	  if (size != 0)
+-- 
+2.7.0.rc3
+
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-8630.patch b/gnu/packages/patches/mit-krb5-CVE-2015-8630.patch
new file mode 100644
index 0000000000..c21d84b1e7
--- /dev/null
+++ b/gnu/packages/patches/mit-krb5-CVE-2015-8630.patch
@@ -0,0 +1,81 @@
+Copied from Fedora.
+http://pkgs.fedoraproject.org/cgit/rpms/krb5.git/tree/krb5-CVE-2015-8630.patch?h=f22
+
+From b863de7fbf080b15e347a736fdda0a82d42f4f6b Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 8 Jan 2016 12:52:28 -0500
+Subject: [PATCH 2/3] Check for null kadm5 policy name [CVE-2015-8630]
+
+In kadm5_create_principal_3() and kadm5_modify_principal(), check for
+entry->policy being null when KADM5_POLICY is included in the mask.
+
+CVE-2015-8630:
+
+In MIT krb5 1.12 and later, an authenticated attacker with permission
+to modify a principal entry can cause kadmind to dereference a null
+pointer by supplying a null policy value but including KADM5_POLICY in
+the mask.
+
+    CVSSv2 Vector: AV:N/AC:H/Au:S/C:N/I:N/A:C/E:POC/RL:OF/RC:C
+
+ticket: 8342 (new)
+target_version: 1.14-next
+target_version: 1.13-next
+tags: pullup
+---
+ src/lib/kadm5/srv/svr_principal.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c
+index 5b95fa3..1d4365c 100644
+--- a/src/lib/kadm5/srv/svr_principal.c
++++ b/src/lib/kadm5/srv/svr_principal.c
+@@ -395,6 +395,8 @@ kadm5_create_principal_3(void *server_handle,
+     /*
+      * Argument sanity checking, and opening up the DB
+      */
++    if (entry == NULL)
++        return EINVAL;
+     if(!(mask & KADM5_PRINCIPAL) || (mask & KADM5_MOD_NAME) ||
+        (mask & KADM5_MOD_TIME) || (mask & KADM5_LAST_PWD_CHANGE) ||
+        (mask & KADM5_MKVNO) || (mask & KADM5_AUX_ATTRIBUTES) ||
+@@ -403,12 +405,12 @@ kadm5_create_principal_3(void *server_handle,
+         return KADM5_BAD_MASK;
+     if ((mask & KADM5_KEY_DATA) && entry->n_key_data != 0)
+         return KADM5_BAD_MASK;
++    if((mask & KADM5_POLICY) && entry->policy == NULL)
++        return KADM5_BAD_MASK;
+     if((mask & KADM5_POLICY) && (mask & KADM5_POLICY_CLR))
+         return KADM5_BAD_MASK;
+     if((mask & ~ALL_PRINC_MASK))
+         return KADM5_BAD_MASK;
+-    if (entry == NULL)
+-        return EINVAL;
+ 
+     /*
+      * Check to see if the principal exists
+@@ -643,6 +645,8 @@ kadm5_modify_principal(void *server_handle,
+ 
+     krb5_clear_error_message(handle->context);
+ 
++    if(entry == NULL)
++        return EINVAL;
+     if((mask & KADM5_PRINCIPAL) || (mask & KADM5_LAST_PWD_CHANGE) ||
+        (mask & KADM5_MOD_TIME) || (mask & KADM5_MOD_NAME) ||
+        (mask & KADM5_MKVNO) || (mask & KADM5_AUX_ATTRIBUTES) ||
+@@ -651,10 +655,10 @@ kadm5_modify_principal(void *server_handle,
+         return KADM5_BAD_MASK;
+     if((mask & ~ALL_PRINC_MASK))
+         return KADM5_BAD_MASK;
++    if((mask & KADM5_POLICY) && entry->policy == NULL)
++        return KADM5_BAD_MASK;
+     if((mask & KADM5_POLICY) && (mask & KADM5_POLICY_CLR))
+         return KADM5_BAD_MASK;
+-    if(entry == (kadm5_principal_ent_t) NULL)
+-        return EINVAL;
+     if (mask & KADM5_TL_DATA) {
+         tl_data_orig = entry->tl_data;
+         while (tl_data_orig) {
+-- 
+2.7.0.rc3
+
diff --git a/gnu/packages/patches/mit-krb5-CVE-2015-8631.patch b/gnu/packages/patches/mit-krb5-CVE-2015-8631.patch
new file mode 100644
index 0000000000..dd1eb2945c
--- /dev/null
+++ b/gnu/packages/patches/mit-krb5-CVE-2015-8631.patch
@@ -0,0 +1,576 @@
+Copied from Fedora.
+http://pkgs.fedoraproject.org/cgit/rpms/krb5.git/tree/krb5-CVE-2015-8631.patch?h=f22
+
+From 83ed75feba32e46f736fcce0d96a0445f29b96c2 Mon Sep 17 00:00:00 2001
+From: Greg Hudson <ghudson@mit.edu>
+Date: Fri, 8 Jan 2016 13:16:54 -0500
+Subject: [PATCH 3/3] Fix leaks in kadmin server stubs [CVE-2015-8631]
+
+In each kadmind server stub, initialize the client_name and
+server_name variables, and release them in the cleanup handler.  Many
+of the stubs will otherwise leak the client and server name if
+krb5_unparse_name() fails.  Also make sure to free the prime_arg
+variables in rename_principal_2_svc(), or we can leak the first one if
+unparsing the second one fails.  Discovered by Simo Sorce.
+
+CVE-2015-8631:
+
+In all versions of MIT krb5, an authenticated attacker can cause
+kadmind to leak memory by supplying a null principal name in a request
+which uses one.  Repeating these requests will eventually cause
+kadmind to exhaust all available memory.
+
+    CVSSv2 Vector: AV:N/AC:L/Au:S/C:N/I:N/A:C/E:POC/RL:OF/RC:C
+
+ticket: 8343 (new)
+target_version: 1.14-next
+target_version: 1.13-next
+tags: pullup
+---
+ src/kadmin/server/server_stubs.c | 151 ++++++++++++++++++++-------------------
+ 1 file changed, 77 insertions(+), 74 deletions(-)
+
+diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c
+index 1879dc6..6ac797e 100644
+--- a/src/kadmin/server/server_stubs.c
++++ b/src/kadmin/server/server_stubs.c
+@@ -334,7 +334,8 @@ create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret          ret;
+     char                        *prime_arg;
+-    gss_buffer_desc             client_name, service_name;
++    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                   minor_stat;
+     kadm5_server_handle_t       handle;
+     restriction_t               *rp;
+@@ -382,10 +383,10 @@ create_principal_2_svc(cprinc_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
+-    gss_release_buffer(&minor_stat, &client_name);
+-    gss_release_buffer(&minor_stat, &service_name);
+ 
+ exit_func:
++    gss_release_buffer(&minor_stat, &client_name);
++    gss_release_buffer(&minor_stat, &service_name);
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -395,7 +396,8 @@ create_principal3_2_svc(cprinc3_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret          ret;
+     char                        *prime_arg;
+-    gss_buffer_desc             client_name, service_name;
++    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                   minor_stat;
+     kadm5_server_handle_t       handle;
+     restriction_t               *rp;
+@@ -444,10 +446,10 @@ create_principal3_2_svc(cprinc3_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
+-    gss_release_buffer(&minor_stat, &client_name);
+-    gss_release_buffer(&minor_stat, &service_name);
+ 
+ exit_func:
++    gss_release_buffer(&minor_stat, &client_name);
++    gss_release_buffer(&minor_stat, &service_name);
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -457,8 +459,8 @@ delete_principal_2_svc(dprinc_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -501,10 +503,10 @@ delete_principal_2_svc(dprinc_arg *arg, struct svc_req *rqstp)
+ 
+     }
+     free(prime_arg);
+-    gss_release_buffer(&minor_stat, &client_name);
+-    gss_release_buffer(&minor_stat, &service_name);
+ 
+ exit_func:
++    gss_release_buffer(&minor_stat, &client_name);
++    gss_release_buffer(&minor_stat, &service_name);
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -514,8 +516,8 @@ modify_principal_2_svc(mprinc_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     restriction_t                   *rp;
+@@ -559,9 +561,9 @@ modify_principal_2_svc(mprinc_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -570,10 +572,9 @@ generic_ret *
+ rename_principal_2_svc(rprinc_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret          ret;
+-    char                        *prime_arg1,
+-        *prime_arg2;
+-    gss_buffer_desc             client_name,
+-        service_name;
++    char                        *prime_arg1 = NULL, *prime_arg2 = NULL;
++    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                   minor_stat;
+     kadm5_server_handle_t       handle;
+     restriction_t               *rp;
+@@ -655,11 +656,11 @@ rename_principal_2_svc(rprinc_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+ 
+     }
++exit_func:
+     free(prime_arg1);
+     free(prime_arg2);
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -669,8 +670,8 @@ get_principal_2_svc(gprinc_arg *arg, struct svc_req *rqstp)
+ {
+     static gprinc_ret               ret;
+     char                            *prime_arg, *funcname;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -719,9 +720,9 @@ get_principal_2_svc(gprinc_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -731,8 +732,8 @@ get_princs_2_svc(gprincs_arg *arg, struct svc_req *rqstp)
+ {
+     static gprincs_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -777,9 +778,9 @@ get_princs_2_svc(gprincs_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+ 
+     }
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -789,8 +790,8 @@ chpass_principal_2_svc(chpass_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -840,9 +841,9 @@ chpass_principal_2_svc(chpass_arg *arg, struct svc_req *rqstp)
+     }
+ 
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -852,8 +853,8 @@ chpass_principal3_2_svc(chpass3_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -909,9 +910,9 @@ chpass_principal3_2_svc(chpass3_arg *arg, struct svc_req *rqstp)
+     }
+ 
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -921,8 +922,8 @@ setv4key_principal_2_svc(setv4key_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -969,9 +970,9 @@ setv4key_principal_2_svc(setv4key_arg *arg, struct svc_req *rqstp)
+     }
+ 
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -981,8 +982,8 @@ setkey_principal_2_svc(setkey_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1029,9 +1030,9 @@ setkey_principal_2_svc(setkey_arg *arg, struct svc_req *rqstp)
+     }
+ 
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1041,8 +1042,8 @@ setkey_principal3_2_svc(setkey3_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1092,9 +1093,9 @@ setkey_principal3_2_svc(setkey3_arg *arg, struct svc_req *rqstp)
+     }
+ 
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1106,8 +1107,8 @@ chrand_principal_2_svc(chrand_arg *arg, struct svc_req *rqstp)
+     krb5_keyblock               *k;
+     int                         nkeys;
+     char                        *prime_arg, *funcname;
+-    gss_buffer_desc             client_name,
+-        service_name;
++    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                   minor_stat;
+     kadm5_server_handle_t       handle;
+     const char                  *errmsg = NULL;
+@@ -1164,9 +1165,9 @@ chrand_principal_2_svc(chrand_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1178,8 +1179,8 @@ chrand_principal3_2_svc(chrand3_arg *arg, struct svc_req *rqstp)
+     krb5_keyblock               *k;
+     int                         nkeys;
+     char                        *prime_arg, *funcname;
+-    gss_buffer_desc             client_name,
+-        service_name;
++    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                   minor_stat;
+     kadm5_server_handle_t       handle;
+     const char                  *errmsg = NULL;
+@@ -1241,9 +1242,9 @@ chrand_principal3_2_svc(chrand3_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1253,8 +1254,8 @@ create_policy_2_svc(cpol_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1295,9 +1296,9 @@ create_policy_2_svc(cpol_arg *arg, struct svc_req *rqstp)
+         if (errmsg != NULL)
+             krb5_free_error_message(handle->context, errmsg);
+     }
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1307,8 +1308,8 @@ delete_policy_2_svc(dpol_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1347,9 +1348,9 @@ delete_policy_2_svc(dpol_arg *arg, struct svc_req *rqstp)
+         if (errmsg != NULL)
+             krb5_free_error_message(handle->context, errmsg);
+     }
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1359,8 +1360,8 @@ modify_policy_2_svc(mpol_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1400,9 +1401,9 @@ modify_policy_2_svc(mpol_arg *arg, struct svc_req *rqstp)
+         if (errmsg != NULL)
+             krb5_free_error_message(handle->context, errmsg);
+     }
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1413,8 +1414,8 @@ get_policy_2_svc(gpol_arg *arg, struct svc_req *rqstp)
+     static gpol_ret             ret;
+     kadm5_ret_t         ret2;
+     char                        *prime_arg, *funcname;
+-    gss_buffer_desc             client_name,
+-        service_name;
++    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                   minor_stat;
+     kadm5_principal_ent_rec     caller_ent;
+     kadm5_server_handle_t       handle;
+@@ -1475,9 +1476,9 @@ get_policy_2_svc(gpol_arg *arg, struct svc_req *rqstp)
+         log_unauth(funcname, prime_arg,
+                    &client_name, &service_name, rqstp);
+     }
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ 
+@@ -1488,8 +1489,8 @@ get_pols_2_svc(gpols_arg *arg, struct svc_req *rqstp)
+ {
+     static gpols_ret                ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1531,9 +1532,9 @@ get_pols_2_svc(gpols_arg *arg, struct svc_req *rqstp)
+         if (errmsg != NULL)
+             krb5_free_error_message(handle->context, errmsg);
+     }
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1541,7 +1542,8 @@ exit_func:
+ getprivs_ret * get_privs_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
+ {
+     static getprivs_ret            ret;
+-    gss_buffer_desc                client_name, service_name;
++    gss_buffer_desc                client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                      minor_stat;
+     kadm5_server_handle_t          handle;
+     const char                     *errmsg = NULL;
+@@ -1571,9 +1573,9 @@ getprivs_ret * get_privs_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
+     if (errmsg != NULL)
+         krb5_free_error_message(handle->context, errmsg);
+ 
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1583,7 +1585,8 @@ purgekeys_2_svc(purgekeys_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret          ret;
+     char                        *prime_arg, *funcname;
+-    gss_buffer_desc             client_name, service_name;
++    gss_buffer_desc             client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc             service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                   minor_stat;
+     kadm5_server_handle_t       handle;
+ 
+@@ -1629,9 +1632,9 @@ purgekeys_2_svc(purgekeys_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1641,8 +1644,8 @@ get_strings_2_svc(gstrings_arg *arg, struct svc_req *rqstp)
+ {
+     static gstrings_ret             ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1688,9 +1691,9 @@ get_strings_2_svc(gstrings_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1700,8 +1703,8 @@ set_string_2_svc(sstring_arg *arg, struct svc_req *rqstp)
+ {
+     static generic_ret              ret;
+     char                            *prime_arg;
+-    gss_buffer_desc                 client_name,
+-        service_name;
++    gss_buffer_desc                 client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc                 service_name = GSS_C_EMPTY_BUFFER;
+     OM_uint32                       minor_stat;
+     kadm5_server_handle_t           handle;
+     const char                      *errmsg = NULL;
+@@ -1744,9 +1747,9 @@ set_string_2_svc(sstring_arg *arg, struct svc_req *rqstp)
+             krb5_free_error_message(handle->context, errmsg);
+     }
+     free(prime_arg);
++exit_func:
+     gss_release_buffer(&minor_stat, &client_name);
+     gss_release_buffer(&minor_stat, &service_name);
+-exit_func:
+     free_server_handle(handle);
+     return &ret;
+ }
+@@ -1754,8 +1757,8 @@ exit_func:
+ generic_ret *init_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
+ {
+     static generic_ret         ret;
+-    gss_buffer_desc            client_name,
+-        service_name;
++    gss_buffer_desc            client_name = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc            service_name = GSS_C_EMPTY_BUFFER;
+     kadm5_server_handle_t      handle;
+     OM_uint32                  minor_stat;
+     const char                 *errmsg = NULL;
+@@ -1797,10 +1800,10 @@ generic_ret *init_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
+                      rqstp->rq_cred.oa_flavor);
+     if (errmsg != NULL)
+         krb5_free_error_message(NULL, errmsg);
+-    gss_release_buffer(&minor_stat, &client_name);
+-    gss_release_buffer(&minor_stat, &service_name);
+ 
+ exit_func:
++    gss_release_buffer(&minor_stat, &client_name);
++    gss_release_buffer(&minor_stat, &service_name);
+     return(&ret);
+ }
+ 
+-- 
+2.7.0.rc3
+
diff --git a/gnu/packages/patches/mit-krb5-init-context-null-spnego.patch b/gnu/packages/patches/mit-krb5-init-context-null-spnego.patch
new file mode 100644
index 0000000000..195db38d08
--- /dev/null
+++ b/gnu/packages/patches/mit-krb5-init-context-null-spnego.patch
@@ -0,0 +1,49 @@
+Copied from Fedora.
+http://pkgs.fedoraproject.org/cgit/rpms/krb5.git/tree/krb5-init_context_null_spnego.patch?h=f22
+
+From 3beb564cea3d219efcf71682b6576cad548c2d23 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Tue, 5 Jan 2016 12:11:59 -0500
+Subject: [PATCH] Check internal context on init context errors
+
+If the mechanism deletes the internal context handle on error, the
+mechglue must do the same with the union context, to avoid crashes if
+the application calls other functions with this invalid union context.
+
+[ghudson@mit.edu: edit commit message and code comment]
+
+ticket: 8337 (new)
+target_version: 1.14-next
+target_version: 1.13-next
+tags: pullup
+---
+ src/lib/gssapi/mechglue/g_init_sec_context.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/src/lib/gssapi/mechglue/g_init_sec_context.c b/src/lib/gssapi/mechglue/g_init_sec_context.c
+index aaae767..9f154b8 100644
+--- a/src/lib/gssapi/mechglue/g_init_sec_context.c
++++ b/src/lib/gssapi/mechglue/g_init_sec_context.c
+@@ -224,12 +224,15 @@ OM_uint32 *		time_rec;
+ 
+     if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
+ 	/*
+-	 * the spec says (the preferred) method is to delete all
+-	 * context info on the first call to init, and on all
+-	 * subsequent calls make the caller responsible for
+-	 * calling gss_delete_sec_context
++	 * The spec says the preferred method is to delete all context info on
++	 * the first call to init, and on all subsequent calls make the caller
++	 * responsible for calling gss_delete_sec_context.  However, if the
++	 * mechanism decided to delete the internal context, we should also
++	 * delete the union context.
+ 	 */
+ 	map_error(minor_status, mech);
++	if (union_ctx_id->internal_ctx_id == GSS_C_NO_CONTEXT)
++	    *context_handle = GSS_C_NO_CONTEXT;
+ 	if (*context_handle == GSS_C_NO_CONTEXT) {
+ 	    free(union_ctx_id->mech_type->elements);
+ 	    free(union_ctx_id->mech_type);
+-- 
+2.6.4
+
diff --git a/gnu/packages/patches/ocaml-findlib-make-install.patch b/gnu/packages/patches/ocaml-findlib-make-install.patch
new file mode 100644
index 0000000000..238f9ca3ce
--- /dev/null
+++ b/gnu/packages/patches/ocaml-findlib-make-install.patch
@@ -0,0 +1,20 @@
+Ocaml wants to install its "core" libraries in OCAML_CORE_STDLIB.  That
+does not work in a store-based distribution.
+
+A solution was already provided by Nix
+
+    https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/tools/ocaml/findlib/install_topfind.patch
+
+regenerated for Guix.
+
+--- findlib-1.5.3/src/findlib/Makefile	2014-09-16 13:21:46.000000000 +0200
++++ findlib-1.5.3/src/findlib/Makefile.new	2014-10-01 14:30:54.141082521 +0200
+@@ -89,7 +89,7 @@
+ install: all
+ 	mkdir -p "$(prefix)$(OCAML_SITELIB)/$(NAME)"
+ 	mkdir -p "$(prefix)$(OCAMLFIND_BIN)"
+-	test $(INSTALL_TOPFIND) -eq 0 || cp topfind "$(prefix)$(OCAML_CORE_STDLIB)"
++	test $(INSTALL_TOPFIND) -eq 0 || cp topfind "$(prefix)$(OCAML_SITELIB)"
+ 	files=`$(TOP)/tools/collect_files $(TOP)/Makefile.config findlib.cmi findlib.mli findlib.cma topfind.cmi topfind.mli fl_package_base.mli fl_package_base.cmi fl_metascanner.mli fl_metascanner.cmi fl_metatoken.cmi findlib_top.cma findlib.cmxa findlib.a findlib.cmxs findlib_dynload.cma findlib_dynload.cmxa findlib_dynload.a findlib_dynload.cmxs fl_dynload.mli fl_dynload.cmi META` && \
+ 	cp $$files "$(prefix)$(OCAML_SITELIB)/$(NAME)"
+ 	f="ocamlfind$(EXEC_SUFFIX)"; { test -f ocamlfind_opt$(EXEC_SUFFIX) && f="ocamlfind_opt$(EXEC_SUFFIX)"; }; \
diff --git a/gnu/packages/patches/python-paste-remove-timing-test.patch b/gnu/packages/patches/python-paste-remove-timing-test.patch
new file mode 100644
index 0000000000..6ab8d1a59c
--- /dev/null
+++ b/gnu/packages/patches/python-paste-remove-timing-test.patch
@@ -0,0 +1,16 @@
+Remove this test to verify that things were modified since a certain time.
+
+That assumption doesn't hold up when your environment doesn't have access to a
+real clock and thinks it's living in 1970 :)
+
+--- a/tests/test_fileapp.py    2015-04-23 13:48:37.000000000 -0700
++++ b/tests/test_fileapp.py	2016-02-22 19:20:08.332802417 -0800
+@@ -223,8 +223,6 @@
+                   status=304)
+     res = app.get('/', headers={'If-None-Match': 'asdf'},
+                   status=200)
+-    res = app.get('/', headers={'If-Modified-Since': 'Sat, 1 Jan 2005 12:00:00 GMT'},
+-                  status=200)
+     res = app.get('/', headers={'If-Modified-Since': last_mod + '; length=100'},
+                   status=304)
+     res = app.get('/', headers={'If-Modified-Since': 'invalid date'},
diff --git a/gnu/packages/patches/python-paste-remove-website-test.patch b/gnu/packages/patches/python-paste-remove-website-test.patch
new file mode 100644
index 0000000000..93417fbe75
--- /dev/null
+++ b/gnu/packages/patches/python-paste-remove-website-test.patch
@@ -0,0 +1,21 @@
+Remove the test to see if the Python Paste website is up.
+
+Obviously without network access there is no way for us to check this, and
+it's pretty strange to test a project's website when you really mean to test
+the project anyhow...
+
+--- a/tests/test_proxy.py	2016-02-22 19:13:04.040117767 -0800
++++ b/tests/test_proxy.py	2016-02-22 19:13:04.040117767 -0800
+@@ -1,12 +1,3 @@
+ from paste import proxy
+ from paste.fixture import TestApp
+
+-def test_paste_website():
+-    # Not the most robust test...
+-    # need to test things like POSTing to pages, and getting from pages
+-    # that don't set content-length.
+-    app = proxy.Proxy('http://pythonpaste.org')
+-    app = TestApp(app)
+-    res = app.get('/')
+-    assert 'documentation' in res
+-
diff --git a/gnu/packages/patches/qemu-CVE-2015-8619.patch b/gnu/packages/patches/qemu-CVE-2015-8619.patch
new file mode 100644
index 0000000000..5961343d1e
--- /dev/null
+++ b/gnu/packages/patches/qemu-CVE-2015-8619.patch
@@ -0,0 +1,119 @@
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Wed, 13 Jan 2016 09:09:58 +0100
+Subject: [PATCH] hmp: fix sendkey out of bounds write (CVE-2015-8619)
+
+When processing 'sendkey' command, hmp_sendkey routine null
+terminates the 'keyname_buf' array. This results in an OOB
+write issue, if 'keyname_len' was to fall outside of
+'keyname_buf' array.
+
+Since the keyname's length is known the keyname_buf can be
+removed altogether by adding a length parameter to
+index_from_key() and using it for the error output as well.
+
+Reported-by: Ling Liu <liuling-it@360.cn>
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Message-Id: <20160113080958.GA18934@olga>
+[Comparison with "<" dumbed down, test for junk after strtoul()
+tweaked]
+Signed-off-by: Markus Armbruster <armbru@redhat.com>
+
+(cherry picked from commit 64ffbe04eaafebf4045a3ace52a360c14959d196)
+---
+ hmp.c                | 18 ++++++++----------
+ include/ui/console.h |  2 +-
+ ui/input-legacy.c    |  5 +++--
+ 3 files changed, 12 insertions(+), 13 deletions(-)
+
+diff --git a/hmp.c b/hmp.c
+index 2140605..1904203 100644
+--- a/hmp.c
++++ b/hmp.c
+@@ -1734,21 +1734,18 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)
+     int has_hold_time = qdict_haskey(qdict, "hold-time");
+     int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
+     Error *err = NULL;
+-    char keyname_buf[16];
+     char *separator;
+     int keyname_len;
+ 
+     while (1) {
+         separator = strchr(keys, '-');
+         keyname_len = separator ? separator - keys : strlen(keys);
+-        pstrcpy(keyname_buf, sizeof(keyname_buf), keys);
+ 
+         /* Be compatible with old interface, convert user inputted "<" */
+-        if (!strncmp(keyname_buf, "<", 1) && keyname_len == 1) {
+-            pstrcpy(keyname_buf, sizeof(keyname_buf), "less");
++        if (keys[0] == '<' && keyname_len == 1) {
++            keys = "less";
+             keyname_len = 4;
+         }
+-        keyname_buf[keyname_len] = 0;
+ 
+         keylist = g_malloc0(sizeof(*keylist));
+         keylist->value = g_malloc0(sizeof(*keylist->value));
+@@ -1761,16 +1758,17 @@ void hmp_sendkey(Monitor *mon, const QDict *qdict)
+         }
+         tmp = keylist;
+ 
+-        if (strstart(keyname_buf, "0x", NULL)) {
++        if (strstart(keys, "0x", NULL)) {
+             char *endp;
+-            int value = strtoul(keyname_buf, &endp, 0);
+-            if (*endp != '\0') {
++            int value = strtoul(keys, &endp, 0);
++            assert(endp <= keys + keyname_len);
++            if (endp != keys + keyname_len) {
+                 goto err_out;
+             }
+             keylist->value->type = KEY_VALUE_KIND_NUMBER;
+             keylist->value->u.number = value;
+         } else {
+-            int idx = index_from_key(keyname_buf);
++            int idx = index_from_key(keys, keyname_len);
+             if (idx == Q_KEY_CODE_MAX) {
+                 goto err_out;
+             }
+@@ -1792,7 +1790,7 @@ out:
+     return;
+ 
+ err_out:
+-    monitor_printf(mon, "invalid parameter: %s\n", keyname_buf);
++    monitor_printf(mon, "invalid parameter: %.*s\n", keyname_len, keys);
+     goto out;
+ }
+ 
+diff --git a/include/ui/console.h b/include/ui/console.h
+index c249db4..5739bdd 100644
+--- a/include/ui/console.h
++++ b/include/ui/console.h
+@@ -433,7 +433,7 @@ static inline int vnc_display_pw_expire(const char *id, time_t expires)
+ void curses_display_init(DisplayState *ds, int full_screen);
+ 
+ /* input.c */
+-int index_from_key(const char *key);
++int index_from_key(const char *key, size_t key_length);
+ 
+ /* gtk.c */
+ void early_gtk_display_init(int opengl);
+diff --git a/ui/input-legacy.c b/ui/input-legacy.c
+index e0a39f0..3f28bbc 100644
+--- a/ui/input-legacy.c
++++ b/ui/input-legacy.c
+@@ -57,12 +57,13 @@ struct QEMUPutLEDEntry {
+ static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers =
+     QTAILQ_HEAD_INITIALIZER(led_handlers);
+ 
+-int index_from_key(const char *key)
++int index_from_key(const char *key, size_t key_length)
+ {
+     int i;
+ 
+     for (i = 0; QKeyCode_lookup[i] != NULL; i++) {
+-        if (!strcmp(key, QKeyCode_lookup[i])) {
++        if (!strncmp(key, QKeyCode_lookup[i], key_length) &&
++            !QKeyCode_lookup[i][key_length]) {
+             break;
+         }
+     }
diff --git a/gnu/packages/patches/qemu-CVE-2016-1981.patch b/gnu/packages/patches/qemu-CVE-2016-1981.patch
new file mode 100644
index 0000000000..03e7b333c9
--- /dev/null
+++ b/gnu/packages/patches/qemu-CVE-2016-1981.patch
@@ -0,0 +1,95 @@
+From: Laszlo Ersek <lersek@redhat.com>
+Date: Tue, 19 Jan 2016 14:17:20 +0100
+Subject: [PATCH] e1000: eliminate infinite loops on out-of-bounds transfer
+ start
+
+The start_xmit() and e1000_receive_iov() functions implement DMA transfers
+iterating over a set of descriptors that the guest's e1000 driver
+prepares:
+
+- the TDLEN and RDLEN registers store the total size of the descriptor
+  area,
+
+- while the TDH and RDH registers store the offset (in whole tx / rx
+  descriptors) into the area where the transfer is supposed to start.
+
+Each time a descriptor is processed, the TDH and RDH register is bumped
+(as appropriate for the transfer direction).
+
+QEMU already contains logic to deal with bogus transfers submitted by the
+guest:
+
+- Normally, the transmit case wants to increase TDH from its initial value
+  to TDT. (TDT is allowed to be numerically smaller than the initial TDH
+  value; wrapping at or above TDLEN bytes to zero is normal.) The failsafe
+  that QEMU currently has here is a check against reaching the original
+  TDH value again -- a complete wraparound, which should never happen.
+
+- In the receive case RDH is increased from its initial value until
+  "total_size" bytes have been received; preferably in a single step, or
+  in "s->rxbuf_size" byte steps, if the latter is smaller. However, null
+  RX descriptors are skipped without receiving data, while RDH is
+  incremented just the same. QEMU tries to prevent an infinite loop
+  (processing only null RX descriptors) by detecting whether RDH assumes
+  its original value during the loop. (Again, wrapping from RDLEN to 0 is
+  normal.)
+
+What both directions miss is that the guest could program TDLEN and RDLEN
+so low, and the initial TDH and RDH so high, that these registers will
+immediately be truncated to zero, and then never reassume their initial
+values in the loop -- a full wraparound will never occur.
+
+The condition that expresses this is:
+
+  xdh_start >= s->mac_reg[XDLEN] / sizeof(desc)
+
+i.e., TDH or RDH start out after the last whole rx or tx descriptor that
+fits into the TDLEN or RDLEN sized area.
+
+This condition could be checked before we enter the loops, but
+pci_dma_read() / pci_dma_write() knows how to fill in buffers safely for
+bogus DMA addresses, so we just extend the existing failsafes with the
+above condition.
+
+This is CVE-2016-1981.
+
+Cc: "Michael S. Tsirkin" <mst@redhat.com>
+Cc: Petr Matousek <pmatouse@redhat.com>
+Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+Cc: Prasad Pandit <ppandit@redhat.com>
+Cc: Michael Roth <mdroth@linux.vnet.ibm.com>
+Cc: Jason Wang <jasowang@redhat.com>
+Cc: qemu-stable@nongnu.org
+RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1296044
+Signed-off-by: Laszlo Ersek <lersek@redhat.com>
+Reviewed-by: Jason Wang <jasowang@redhat.com>
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+(cherry picked from commit dd793a74882477ca38d49e191110c17dfee51dcc)
+---
+ hw/net/e1000.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/hw/net/e1000.c b/hw/net/e1000.c
+index bec06e9..34d0823 100644
+--- a/hw/net/e1000.c
++++ b/hw/net/e1000.c
+@@ -908,7 +908,8 @@ start_xmit(E1000State *s)
+          * bogus values to TDT/TDLEN.
+          * there's nothing too intelligent we could do about this.
+          */
+-        if (s->mac_reg[TDH] == tdh_start) {
++        if (s->mac_reg[TDH] == tdh_start ||
++            tdh_start >= s->mac_reg[TDLEN] / sizeof(desc)) {
+             DBGOUT(TXERR, "TDH wraparound @%x, TDT %x, TDLEN %x\n",
+                    tdh_start, s->mac_reg[TDT], s->mac_reg[TDLEN]);
+             break;
+@@ -1165,7 +1166,8 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
+         if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN])
+             s->mac_reg[RDH] = 0;
+         /* see comment in start_xmit; same here */
+-        if (s->mac_reg[RDH] == rdh_start) {
++        if (s->mac_reg[RDH] == rdh_start ||
++            rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) {
+             DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
+                    rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
+             set_ics(s, 0, E1000_ICS_RXO);
diff --git a/gnu/packages/patches/qemu-CVE-2016-2197.patch b/gnu/packages/patches/qemu-CVE-2016-2197.patch
new file mode 100644
index 0000000000..d851e1ec75
--- /dev/null
+++ b/gnu/packages/patches/qemu-CVE-2016-2197.patch
@@ -0,0 +1,40 @@
+From: John Snow <jsnow@redhat.com>
+Date: Wed, 10 Feb 2016 13:29:40 -0500
+Subject: [PATCH] ahci: Do not unmap NULL addresses
+
+Definitely don't try to unmap a garbage address.
+
+Reported-by: Zuozhi fzz <zuozhi.fzz@alibaba-inc.com>
+Signed-off-by: John Snow <jsnow@redhat.com>
+Message-id: 1454103689-13042-2-git-send-email-jsnow@redhat.com
+(cherry picked from commit 99b4cb71069f109b79b27bc629fc0cf0886dbc4b)
+---
+ hw/ide/ahci.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
+index 17f1cbd..cdc9299 100644
+--- a/hw/ide/ahci.c
++++ b/hw/ide/ahci.c
+@@ -661,6 +661,10 @@ static bool ahci_map_fis_address(AHCIDevice *ad)
+ 
+ static void ahci_unmap_fis_address(AHCIDevice *ad)
+ {
++    if (ad->res_fis == NULL) {
++        DPRINTF(ad->port_no, "Attempt to unmap NULL FIS address\n");
++        return;
++    }
+     dma_memory_unmap(ad->hba->as, ad->res_fis, 256,
+                      DMA_DIRECTION_FROM_DEVICE, 256);
+     ad->res_fis = NULL;
+@@ -677,6 +681,10 @@ static bool ahci_map_clb_address(AHCIDevice *ad)
+ 
+ static void ahci_unmap_clb_address(AHCIDevice *ad)
+ {
++    if (ad->lst == NULL) {
++        DPRINTF(ad->port_no, "Attempt to unmap NULL CLB address\n");
++        return;
++    }
+     dma_memory_unmap(ad->hba->as, ad->lst, 1024,
+                      DMA_DIRECTION_FROM_DEVICE, 1024);
+     ad->lst = NULL;
diff --git a/gnu/packages/patches/qemu-usb-ehci-oob-read.patch b/gnu/packages/patches/qemu-usb-ehci-oob-read.patch
new file mode 100644
index 0000000000..d63c0832b8
--- /dev/null
+++ b/gnu/packages/patches/qemu-usb-ehci-oob-read.patch
@@ -0,0 +1,49 @@
+From: Prasad J Pandit <pjp@fedoraproject.org>
+Date: Wed, 20 Jan 2016 01:26:46 +0530
+Subject: [PATCH] usb: check page select value while processing iTD
+
+While processing isochronous transfer descriptors(iTD), the page
+select(PG) field value could lead to an OOB read access. Add
+check to avoid it.
+
+Reported-by: Qinghao Tang <luodalongde@gmail.com>
+Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
+Message-id: 1453233406-12165-1-git-send-email-ppandit@redhat.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+(cherry picked from commit 49d925ce50383a286278143c05511d30ec41a36e)
+---
+ hw/usb/hcd-ehci.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
+index d07f228..c40013e 100644
+--- a/hw/usb/hcd-ehci.c
++++ b/hw/usb/hcd-ehci.c
+@@ -1404,21 +1404,23 @@ static int ehci_process_itd(EHCIState *ehci,
+         if (itd->transact[i] & ITD_XACT_ACTIVE) {
+             pg   = get_field(itd->transact[i], ITD_XACT_PGSEL);
+             off  = itd->transact[i] & ITD_XACT_OFFSET_MASK;
+-            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
+-            ptr2 = (itd->bufptr[pg+1] & ITD_BUFPTR_MASK);
+             len  = get_field(itd->transact[i], ITD_XACT_LENGTH);
+ 
+             if (len > max * mult) {
+                 len = max * mult;
+             }
+-
+-            if (len > BUFF_SIZE) {
++            if (len > BUFF_SIZE || pg > 6) {
+                 return -1;
+             }
+ 
++            ptr1 = (itd->bufptr[pg] & ITD_BUFPTR_MASK);
+             qemu_sglist_init(&ehci->isgl, ehci->device, 2, ehci->as);
+             if (off + len > 4096) {
+                 /* transfer crosses page border */
++                if (pg == 6) {
++                    return -1;  /* avoid page pg + 1 */
++                }
++                ptr2 = (itd->bufptr[pg + 1] & ITD_BUFPTR_MASK);
+                 uint32_t len2 = off + len - 4096;
+                 uint32_t len1 = len - len2;
+                 qemu_sglist_add(&ehci->isgl, ptr1 + off, len1);
diff --git a/gnu/packages/patches/slurm-configure-remove-nonfree-contribs.patch b/gnu/packages/patches/slurm-configure-remove-nonfree-contribs.patch
new file mode 100644
index 0000000000..b63d5bb018
--- /dev/null
+++ b/gnu/packages/patches/slurm-configure-remove-nonfree-contribs.patch
@@ -0,0 +1,43 @@
+From 53eda9102b969a4be2882cea4befee03591a7436 Mon Sep 17 00:00:00 2001
+From: Pjotr Prins <pjotr.public01@thebird.nl>
+Date: Fri, 12 Feb 2016 12:43:33 +0100
+Subject: [PATCH] Remove contribs
+
+---
+ configure.ac | 20 --------------------
+ 1 file changed, 20 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index fedf354..e010732 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -438,26 +438,6 @@ dnl All slurm Makefiles:
+ AC_CONFIG_FILES([Makefile
+ 		 config.xml
+ 		 auxdir/Makefile
+-		 contribs/Makefile
+-		 contribs/cray/Makefile
+-		 contribs/cray/csm/Makefile
+-		 contribs/lua/Makefile
+-		 contribs/mic/Makefile
+-		 contribs/pam/Makefile
+-		 contribs/pam_slurm_adopt/Makefile
+-		 contribs/perlapi/Makefile
+-		 contribs/perlapi/libslurm/Makefile
+-		 contribs/perlapi/libslurm/perl/Makefile.PL
+-		 contribs/perlapi/libslurmdb/Makefile
+-		 contribs/perlapi/libslurmdb/perl/Makefile.PL
+-		 contribs/torque/Makefile
+-		 contribs/phpext/Makefile
+-		 contribs/phpext/slurm_php/config.m4
+-		 contribs/sgather/Makefile
+-		 contribs/sgi/Makefile
+-		 contribs/sjobexit/Makefile
+-		 contribs/slurmdb-direct/Makefile
+-		 contribs/pmi2/Makefile
+ 		 doc/Makefile
+ 		 doc/man/Makefile
+ 		 doc/man/man1/Makefile
+-- 
+2.1.4
+
diff --git a/gnu/packages/patches/tclxml-3.2-install.patch b/gnu/packages/patches/tclxml-3.2-install.patch
new file mode 100644
index 0000000000..09d59925bf
--- /dev/null
+++ b/gnu/packages/patches/tclxml-3.2-install.patch
@@ -0,0 +1,17 @@
+Install everything in PREFIX, set EXTRA_PATH to find it there.
+
+--- ./Makefile.in~	2016-02-06 01:29:16.595090365 +0100
++++ ./Makefile.in	2016-02-06 09:29:04.286008931 +0100
+@@ -133,9 +133,9 @@
+ # require for testing here (like TCLX_LIBRARY).
+ #========================================================================
+
+-EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR)
++EXTRA_PATH	= $(top_builddir):$(TCL_BIN_DIR):$(libdir)
+ #EXTRA_PATH     = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
+-TCLLIBPATH      = $(top_builddir)
++TCLLIBPATH      = $(pkglibdir)
+ TCLSH_ENV	= TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \
+ 		  @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
+ 		  PATH="$(EXTRA_PATH):$(PATH)" \
+ 
\ No newline at end of file
diff --git a/gnu/packages/patches/xf86-video-mga-glibc-2.20.patch b/gnu/packages/patches/xf86-video-mga-glibc-2.20.patch
deleted file mode 100644
index 3b8277df80..0000000000
--- a/gnu/packages/patches/xf86-video-mga-glibc-2.20.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-Fix test compilation with exa.h in configure when using glibc 2.20.
-Inspired by a patch by Peter Hutterer <peter.hutterer@who-t.net>.
-See <https://raw.githubusercontent.com/openembedded/oe-core/master/meta/recipes-graphics/xorg-driver/xf86-input-synaptics/always_include_xorg_server.h.patch>.
-
---- xf86-video-mga-1.6.3/configure.~1~	2013-12-04 21:10:25.000000000 -0500
-+++ xf86-video-mga-1.6.3/configure	2014-12-19 01:06:23.005774736 -0500
-@@ -18464,7 +18464,9 @@
- 
-     SAVE_CPPFLAGS="$CPPFLAGS"
-     CPPFLAGS="$CPPFLAGS $XORG_CFLAGS"
--    ac_fn_c_check_header_mongrel "$LINENO" "exa.h" "ac_cv_header_exa_h" "$ac_includes_default"
-+    ac_fn_c_check_header_mongrel "$LINENO" "exa.h" "ac_cv_header_exa_h" "$ac_includes_default
-+#include <xorg-server.h>
-+"
- if test "x$ac_cv_header_exa_h" = xyes; then :
-   have_exa_h="yes"
- else
diff --git a/gnu/packages/patches/xf86-video-r128-glibc-2.20.patch b/gnu/packages/patches/xf86-video-r128-glibc-2.20.patch
deleted file mode 100644
index 21a430ebc6..0000000000
--- a/gnu/packages/patches/xf86-video-r128-glibc-2.20.patch
+++ /dev/null
@@ -1,17 +0,0 @@
-Fix test compilation with exa.h in configure when using glibc 2.20.
-Inspired by a patch by Peter Hutterer <peter.hutterer@who-t.net>.
-See <https://raw.githubusercontent.com/openembedded/oe-core/master/meta/recipes-graphics/xorg-driver/xf86-input-synaptics/always_include_xorg_server.h.patch>.
-
---- xf86-video-r128-6.9.2/configure.~1~	2013-10-02 14:38:15.000000000 -0400
-+++ xf86-video-r128-6.9.2/configure	2014-12-19 01:23:03.346735159 -0500
-@@ -18400,7 +18400,9 @@
- 
-         SAVE_CPPFLAGS="$CPPFLAGS"
-         CPPFLAGS="$CPPFLAGS $XORG_CFLAGS"
--        ac_fn_c_check_header_mongrel "$LINENO" "exa.h" "ac_cv_header_exa_h" "$ac_includes_default"
-+        ac_fn_c_check_header_mongrel "$LINENO" "exa.h" "ac_cv_header_exa_h" "$ac_includes_default
-+#include <xorg-server.h>
-+"
- if test "x$ac_cv_header_exa_h" = xyes; then :
-   have_exa_h="yes"
- else
diff --git a/gnu/packages/patches/xf86-video-siliconmotion-remove-mibstore.patch b/gnu/packages/patches/xf86-video-siliconmotion-remove-mibstore.patch
deleted file mode 100644
index 5fd9100609..0000000000
--- a/gnu/packages/patches/xf86-video-siliconmotion-remove-mibstore.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-Removes references to mibstore.h and miInitializeBackingStore, which
-have been removed from xorg-server.  Zack Rusin <zackr@vmware.com>
-wrote: "It was a noop for at least 5 years and it has been removed."
-See: http://patches.openembedded.org/patch/46133/
-
---- xf86-video-siliconmotion-1.7.7/src/smi_driver.c.~1~	2012-07-17 00:53:21.000000000 -0400
-+++ xf86-video-siliconmotion-1.7.7/src/smi_driver.c	2014-12-19 01:30:16.708884086 -0500
-@@ -1750,8 +1750,6 @@
- 		   "Done writing mode.  Register dump:\n");
-     SMI_PrintRegs(pScrn);
- 
--    miInitializeBackingStore(pScreen);
--
- #ifdef HAVE_XMODES
-     xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset));
- #endif
diff --git a/gnu/packages/patches/xf86-video-sis-fix-exa-crash.patch b/gnu/packages/patches/xf86-video-sis-fix-exa-crash.patch
deleted file mode 100644
index f5cd0b9a9e..0000000000
--- a/gnu/packages/patches/xf86-video-sis-fix-exa-crash.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-Fix X server crash when sis driver is used with EXA acceleration.
-
-Source: http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/trusty/xserver-xorg-video-sis/trusty/revision/24/debian/patches/fix-exa-crash.diff
-
-The patch was originally proposed by nihui:
-https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-sis/+bug/1066464/comments/13
-
---- a/src/sis310_accel.c
-+++ b/src/sis310_accel.c
-@@ -1874,7 +1874,7 @@
- {
- 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
- 	SISPtr pSiS = SISPTR(pScrn);
--	unsigned char *dst = pDst->devPrivate.ptr;
-+	unsigned char *dst = ((unsigned char *) pSiS->FbBase) + exaGetPixmapOffset(pDst);
- 	int dst_pitch = exaGetPixmapPitch(pDst);
- 
- 	(pSiS->SyncAccel)(pScrn);
-@@ -1882,7 +1882,7 @@
- 	if(pDst->drawable.bitsPerPixel < 8)
- 	   return FALSE;
- 
--	dst += (x * pDst->drawable.bitsPerPixel / 8) + (y * src_pitch);
-+	dst += (x * pDst->drawable.bitsPerPixel / 8) + (y * dst_pitch);
- 	while(h--) {
- 	   SiSMemCopyToVideoRam(pSiS, dst, (unsigned char *)src,
- 				(w * pDst->drawable.bitsPerPixel / 8));
-@@ -1953,7 +1953,7 @@
- {
- 	ScrnInfoPtr pScrn = xf86ScreenToScrn(pSrc->drawable.pScreen);
- 	SISPtr pSiS = SISPTR(pScrn);
--	unsigned char *src = pSrc->devPrivate.ptr;
-+	unsigned char *src = ((unsigned char *) pSiS->FbBase) + exaGetPixmapOffset(pSrc);
- 	int src_pitch = exaGetPixmapPitch(pSrc);
- 	int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
- 
-@@ -1964,7 +1964,7 @@
- 
- 	src += (x * pSrc->drawable.bitsPerPixel / 8) + (y * src_pitch);
- 	while(h--) {
--	   SiSMemCopyFromVideoRam(pSiS, (unsigned char *)dst, src, size);
-+	   SiSMemCopyFromVideoRam(pSiS, (unsigned char *)dst, src, (w * pSrc->drawable.bitsPerPixel / 8));
- 	   src += src_pitch;
- 	   dst += dst_pitch;
- 	}
diff --git a/gnu/packages/patches/xf86-video-sis-update-api.patch b/gnu/packages/patches/xf86-video-sis-update-api.patch
deleted file mode 100644
index d8c5c07273..0000000000
--- a/gnu/packages/patches/xf86-video-sis-update-api.patch
+++ /dev/null
@@ -1,128 +0,0 @@
-Update xf86-video-sis to the current xorg-server API.
-
-Copied from: http://pkgs.fedoraproject.org/cgit/xorg-x11-drv-sis.git/tree/sis-0.10.7-git.patch?id=2705859f0ddc7ee7a3b07f21b442ebeab5df1276
-Commit log: http://pkgs.fedoraproject.org/cgit/xorg-x11-drv-sis.git/log/sis-0.10.7-git.patch
-
-Patch by Adam Jackson <ajax@redhat.com>
-
-diff --git a/src/sis.h b/src/sis.h
-index 46fca2a..20e6134 100644
---- a/src/sis.h
-+++ b/src/sis.h
-@@ -75,7 +75,6 @@
- 
- #include "compiler.h"
- #include "xf86Pci.h"
--#include "xf86Priv.h"
- #include "xf86_OSproc.h"
- #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
- #include "xf86Resources.h"
-diff --git a/src/sis_driver.c b/src/sis_driver.c
-index 61e8075..0fd83d7 100644
---- a/src/sis_driver.c
-+++ b/src/sis_driver.c
-@@ -57,7 +57,6 @@
- #include "fb.h"
- #include "micmap.h"
- #include "mipointer.h"
--#include "mibstore.h"
- #include "edid.h"
- 
- #define SIS_NEED_inSISREG
-@@ -94,6 +93,10 @@
- #include "dri.h"
- #endif
- 
-+#ifndef DEFAULT_DPI
-+#define DEFAULT_DPI 96
-+#endif
-+
- /*
-  * LookupWindow was removed with video abi 11.
-  */
-@@ -7344,7 +7347,11 @@ SISUnmapMem(ScrnInfoPtr pScrn)
-         if(pSiSEnt->MapCountIOBase) {
- 	    pSiSEnt->MapCountIOBase--;
- 	    if((pSiSEnt->MapCountIOBase == 0) || (pSiSEnt->forceUnmapIOBase)) {
-+#ifndef XSERVER_LIBPCIACCESS
- 		xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBase, (pSiS->mmioSize * 1024));
-+#else
-+	        pci_device_unmap_range(pSiS->PciInfo, pSiSEnt->IOBase, (pSiS->mmioSize * 1024));
-+#endif
- 		pSiSEnt->IOBase = NULL;
- 		pSiSEnt->MapCountIOBase = 0;
- 		pSiSEnt->forceUnmapIOBase = FALSE;
-@@ -7355,7 +7362,11 @@ SISUnmapMem(ScrnInfoPtr pScrn)
- 	if(pSiSEnt->MapCountIOBaseDense) {
- 	    pSiSEnt->MapCountIOBaseDense--;
- 	    if((pSiSEnt->MapCountIOBaseDense == 0) || (pSiSEnt->forceUnmapIOBaseDense)) {
-+#ifndef XSERVER_LIBPCIACCESS
- 		xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024));
-+#else
-+		pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiSEnt->IOBaseDense, (pSiS->mmioSize * 1024));
-+#endif
- 		pSiSEnt->IOBaseDense = NULL;
- 		pSiSEnt->MapCountIOBaseDense = 0;
- 		pSiSEnt->forceUnmapIOBaseDense = FALSE;
-@@ -7366,7 +7377,11 @@ SISUnmapMem(ScrnInfoPtr pScrn)
- 	if(pSiSEnt->MapCountFbBase) {
- 	    pSiSEnt->MapCountFbBase--;
- 	    if((pSiSEnt->MapCountFbBase == 0) || (pSiSEnt->forceUnmapFbBase)) {
-+#ifndef XSERVER_LIBPCIACCESS
- 		xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize);
-+#else
-+		pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiSEnt->RealFbBase, pSiS->FbMapSize);
-+#endif
- 		pSiSEnt->FbBase = pSiSEnt->RealFbBase = NULL;
- 		pSiSEnt->MapCountFbBase = 0;
- 		pSiSEnt->forceUnmapFbBase = FALSE;
-@@ -7376,13 +7391,25 @@ SISUnmapMem(ScrnInfoPtr pScrn)
- 	}
-     } else {
- #endif
-+#ifndef XSERVER_LIBPCIACCESS
- 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024));
-+#else
-+	pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->IOBase, (pSiS->mmioSize * 1024));
-+#endif
- 	pSiS->IOBase = NULL;
- #ifdef __alpha__
-+#ifndef XSERVER_LIBPCIACCESS
- 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024));
-+#else
-+	pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->IOBaseDense, (pSiS->mmioSize * 1024));
-+#endif
- 	pSiS->IOBaseDense = NULL;
- #endif
-+#ifndef XSERVER_LIBPCIACCESS
- 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSiS->RealFbBase, pSiS->FbMapSize);
-+#else
-+	pci_device_unmap_range(pSiS->PciInfo, (pointer)pSiS->RealFbBase, pSiS->FbMapSize);
-+#endif
- 	pSiS->FbBase = pSiS->RealFbBase = NULL;
- #ifdef SISDUALHEAD
-     }
-@@ -8859,7 +8886,6 @@ SISScreenInit(SCREEN_INIT_ARGS_DECL)
-     }
-     pSiS->SiSFastVidCopyDone = TRUE;
- 
--    miInitializeBackingStore(pScreen);
-     xf86SetBackingStore(pScreen);
-     xf86SetSilkenMouse(pScreen);
- 
-@@ -9352,7 +9378,14 @@ SISMergedPointerMoved(SCRN_ARG_TYPE arg, int x, int y)
-      }
-      if(doit) {
- 	sigstate = xf86BlockSIGIO();
--#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 15
-+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 18
-+        {
-+            double dx = x, dy = y;
-+            miPointerSetPosition(inputInfo.pointer, Absolute, &dx, &dy, NULL, NULL);
-+            x = (int)dx;
-+            y = (int)dy;
-+        }
-+#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 15
-         {
-             double dx = x, dy = y;
-             miPointerSetPosition(inputInfo.pointer, Absolute, &dx, &dy);
diff --git a/gnu/packages/patches/xf86-video-tdfx-remove-mibstore.patch b/gnu/packages/patches/xf86-video-tdfx-remove-mibstore.patch
deleted file mode 100644
index 05e2154433..0000000000
--- a/gnu/packages/patches/xf86-video-tdfx-remove-mibstore.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-Removes references to mibstore.h and miInitializeBackingStore, which
-have been removed from xorg-server.  Zack Rusin <zackr@vmware.com>
-wrote: "It was a noop for at least 5 years and it has been removed."
-See: http://patches.openembedded.org/patch/46133/
-
---- xf86-video-tdfx-1.4.5/src/tdfx_driver.c.~1~	2012-07-17 01:21:16.000000000 -0400
-+++ xf86-video-tdfx-1.4.5/src/tdfx_driver.c	2014-12-19 01:36:42.762798424 -0500
-@@ -62,10 +62,6 @@
- 
- #include "compiler.h"
- 
--/* Drivers using the mi implementation of backing store need: */
--
--#include "mibstore.h"
--
- /* All drivers using the vgahw module need this */
- /* This driver needs to be modified to not use vgaHW for multihead operation */
- #include "vgaHW.h"
-@@ -2373,7 +2369,6 @@
-     }
-   }
- 
--  miInitializeBackingStore(pScreen);
-   xf86SetBackingStore(pScreen);
-   xf86SetSilkenMouse(pScreen);
- 
diff --git a/gnu/packages/patches/xf86-video-trident-remove-mibstore.patch b/gnu/packages/patches/xf86-video-trident-remove-mibstore.patch
deleted file mode 100644
index 74c89878e7..0000000000
--- a/gnu/packages/patches/xf86-video-trident-remove-mibstore.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-Removes references to mibstore.h and miInitializeBackingStore, which
-have been removed from xorg-server.  Zack Rusin <zackr@vmware.com>
-wrote: "It was a noop for at least 5 years and it has been removed."
-See: http://patches.openembedded.org/patch/46133/
-
---- xf86-video-trident-1.3.6/src/trident_driver.c.~1~	2012-07-15 22:16:00.000000000 -0400
-+++ xf86-video-trident-1.3.6/src/trident_driver.c	2014-12-19 01:45:29.529410518 -0500
-@@ -56,7 +56,6 @@
- 
- #include "mipointer.h"
- 
--#include "mibstore.h"
- #include "shadow.h"
- #include "trident.h"
- #include "trident_regs.h"
-@@ -3037,7 +3036,6 @@
-     	TridentAccelInit(pScreen);
-     }
- 
--    miInitializeBackingStore(pScreen);
-     xf86SetBackingStore(pScreen);
- 
-     /* Initialise cursor functions */
diff --git a/gnu/packages/patches/xf86-video-vmware-glibc-2.20.patch b/gnu/packages/patches/xf86-video-vmware-glibc-2.20.patch
deleted file mode 100644
index 43d21d13ab..0000000000
--- a/gnu/packages/patches/xf86-video-vmware-glibc-2.20.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-Allow builds with glibc 2.20.
-Based on a patch by Peter Hutterer <peter.hutterer@who-t.net>.
-See <https://raw.githubusercontent.com/openembedded/oe-core/master/meta/recipes-graphics/xorg-driver/xf86-input-synaptics/always_include_xorg_server.h.patch>.
-
---- xf86-video-vmware-13.0.2/vmwgfx/vmwgfx_overlay.c.~1~	2014-03-20 09:15:03.000000000 -0400
-+++ xf86-video-vmware-13.0.2/vmwgfx/vmwgfx_overlay.c	2014-12-19 02:31:34.759122552 -0500
-@@ -35,6 +35,8 @@
-  */
- 
- 
-+#include <xorg-server.h>
-+
- #include "xf86xv.h"
- #include "fourcc.h"
- #define debug_printf(...)
diff --git a/gnu/packages/pdf.scm b/gnu/packages/pdf.scm
index 4b30bf09d5..a99fdd70ae 100644
--- a/gnu/packages/pdf.scm
+++ b/gnu/packages/pdf.scm
@@ -55,7 +55,7 @@
    (version "0.37.0")
    (source (origin
             (method url-fetch)
-            (uri (string-append "http://poppler.freedesktop.org/poppler-"
+            (uri (string-append "https://poppler.freedesktop.org/poppler-"
                                 version ".tar.xz"))
             (sha256 (base32
                      "1vjvd0md8y37hlq3lsj0l01a3v3mzm572rzpn1311frvmrg9r7xq"))))
diff --git a/gnu/packages/perl.scm b/gnu/packages/perl.scm
index 0e63aa943e..6ca62aa2ae 100644
--- a/gnu/packages/perl.scm
+++ b/gnu/packages/perl.scm
@@ -2758,9 +2758,9 @@ versa using either JSON::XS or JSON::PP.")
     (build-system perl-build-system)
     (native-inputs
      `(("perl-test-fatal" ,perl-test-fatal)
-       ("perl-test-requires", perl-test-requires)
-       ("perl-test-warnings", perl-test-warnings)
-       ("perl-test-without-module", perl-test-without-module)))
+       ("perl-test-requires" ,perl-test-requires)
+       ("perl-test-warnings" ,perl-test-warnings)
+       ("perl-test-without-module" ,perl-test-without-module)))
     (propagated-inputs
      `(("perl-namespace-clean" ,perl-namespace-clean)))
     (home-page "http://search.cpan.org/dist/JSON-Any")
@@ -6277,4 +6277,27 @@ really be high enough to warrant the use of a keyword, and the size so small
 such that being individual extensions would be wasteful.")
     (license (package-license perl))))
 
+(define-public perl-shell-command
+  (package
+    (name "perl-shell-command")
+    (version "0.06")
+    (source
+      (origin
+        (method url-fetch)
+        (uri (string-append
+               "mirror://cpan/authors/id/F/FL/FLORA/Shell-Command-"
+               version
+               ".tar.gz"))
+        (sha256
+          (base32
+            "1lgc2rb3b5a4lxvbq0cbg08qk0n2i88srxbsz93bwi3razpxxr7k"))))
+    (build-system perl-build-system)
+    (home-page
+      "http://search.cpan.org/dist/Shell-Command")
+    (synopsis
+      "Cross-platform functions emulating common shell commands")
+    (description
+      "Shell::Command is a thin wrapper around ExtUtils::Command.")
+    (license (package-license perl))))
+
 ;;; END: Core module overrides
diff --git a/gnu/packages/pkg-config.scm b/gnu/packages/pkg-config.scm
index 5923395dec..d7cc454e03 100644
--- a/gnu/packages/pkg-config.scm
+++ b/gnu/packages/pkg-config.scm
@@ -33,9 +33,17 @@
    (version "0.29")
    (source (origin
             (method url-fetch)
-            (uri (string-append
-                  "http://pkgconfig.freedesktop.org/releases/pkg-config-"
-                  version ".tar.gz"))
+            (uri (list
+                  (string-append
+                   "http://fossies.org/linux/misc/pkg-config-" version
+                   ".tar.gz")
+
+                  ;; FIXME: The following URL redirects to HTTPS, which
+                  ;; creates bootstrapping problems:
+                  ;; <http://bugs.gnu.org/22774>.
+                  (string-append
+                   "http://pkgconfig.freedesktop.org/releases/pkg-config-"
+                   version ".tar.gz")))
             (sha256
              (base32
               "0sq09a39wj4cxf8l2jvkq067g08ywfma4v6nhprnf351s82pfl68"))))
diff --git a/gnu/packages/polkit.scm b/gnu/packages/polkit.scm
index 4cafb45d92..4f21612804 100644
--- a/gnu/packages/polkit.scm
+++ b/gnu/packages/polkit.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2014 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2015 Andy Wingo <wingo@igalia.com>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -42,7 +43,7 @@
     (source (origin
              (method url-fetch)
              (uri (string-append
-                   "http://www.freedesktop.org/software/polkit/releases/"
+                   "https://www.freedesktop.org/software/polkit/releases/"
                    name "-" version ".tar.gz"))
              (sha256
               (base32
@@ -139,11 +140,11 @@ for unprivileged applications.")
                "1ip78x20hjqvm08kxhp6gb8hf6k5n6sxyx6kk2yvvq53djzh7yv7"))))
     (build-system cmake-build-system)
     (inputs
-      `(("polkit" ,polkit)))
+     `(("polkit" ,polkit)))
     (propagated-inputs
-      `(("qt" ,qt-4))) ; according to the pkg-config files
+     `(("qt" ,qt))) ; qt-4 according to the pkg-config files
     (native-inputs
-      `(("pkg-config", pkg-config)))
+     `(("pkg-config" ,pkg-config)))
     (arguments
      `(#:configure-flags (list (string-append "-DCMAKE_INSTALL_RPATH="
                                               (assoc-ref %outputs "out")
diff --git a/gnu/packages/pulseaudio.scm b/gnu/packages/pulseaudio.scm
index fe976a92f4..8c37b2a3f1 100644
--- a/gnu/packages/pulseaudio.scm
+++ b/gnu/packages/pulseaudio.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
-;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -43,17 +44,14 @@
 (define libsndfile
   (package
     (name "libsndfile")
-    (version "1.0.25")
+    (version "1.0.26")
     (source (origin
              (method url-fetch)
              (uri (string-append "http://www.mega-nerd.com/libsndfile/files/libsndfile-"
                                  version ".tar.gz"))
              (sha256
               (base32
-               "10j8mbb65xkyl0kfy0hpzpmrp0jkr12c7mfycqipxgka6ayns0ar"))
-             (patches
-              (map search-patch '("libsndfile-CVE-2014-9496.patch"
-                                  "libsndfile-CVE-2015-7805.patch")))))
+               "14jhla289cj45946h0hq2an0a9g4wkwb3v4571bla6ixfvn20rfd"))))
     (build-system gnu-build-system)
     (inputs
      `(("libvorbis" ,libvorbis)
@@ -117,15 +115,15 @@ rates.")
 (define pulseaudio
   (package
     (name "pulseaudio")
-    (version "6.0")
+    (version "8.0")
     (source (origin
              (method url-fetch)
              (uri (string-append
-                   "http://freedesktop.org/software/pulseaudio/releases/pulseaudio-"
-                   version ".tar.xz"))
+                   "https://freedesktop.org/software/pulseaudio/releases/"
+                   name "-" version ".tar.xz"))
              (sha256
               (base32
-               "1xpnfxa0d8pgf6b4qdgnkcvrvdxbbbjd5ync19h0f5hbp3h401mm"))
+               "128rrlvrgb4ia3pbzipf5mi6nvrpm6zmxn5r3bynqiikhvify3k9"))
              (modules '((guix build utils)))
              (snippet
               ;; Disable console-kit support by default since it's deprecated
@@ -198,7 +196,7 @@ sound server.")
     (source (origin
              (method url-fetch)
              (uri (string-append
-                   "http://freedesktop.org/software/pulseaudio/pavucontrol/pavucontrol-"
+                   "https://freedesktop.org/software/pulseaudio/pavucontrol/pavucontrol-"
                    version
                    ".tar.xz"))
              (sha256
diff --git a/gnu/packages/pumpio.scm b/gnu/packages/pumpio.scm
index 27a1250ae9..821090790e 100644
--- a/gnu/packages/pumpio.scm
+++ b/gnu/packages/pumpio.scm
@@ -24,7 +24,6 @@
   #:use-module (guix git-download)
   #:use-module (guix build-system gnu)
   #:use-module (gnu packages aspell)
-  #:use-module (gnu packages kde)
   #:use-module (gnu packages qt)
   #:use-module (gnu packages web))
 
diff --git a/gnu/packages/python.scm b/gnu/packages/python.scm
index 987e1238ff..2e485a9aff 100644
--- a/gnu/packages/python.scm
+++ b/gnu/packages/python.scm
@@ -17,6 +17,7 @@
 ;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;; Copyright © 2015 Kyle Meyer <kyle@kyleam.com>
 ;;; Copyright © 2015 Chris Marusich <cmmarusich@gmail.com>
+;;; Copyright © 2016 Danny Milosavljevic <dannym+a@scratchpost.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -37,7 +38,7 @@
   #: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+
-                          isc mpl2.0 psfl public-domain unlicense x11-style
+                          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)
@@ -320,8 +321,8 @@ data types.")
                   (lambda (old new)
                     (symlink (string-append python old)
                              (string-append bin "/" new)))
-                  `("python3", "pydoc3", "idle3")
-                  `("python",  "pydoc",  "idle"))))))
+                  `("python3" ,"pydoc3" ,"idle3")
+                  `("python"  ,"pydoc"  ,"idle"))))))
     (synopsis "Wrapper for the Python 3 commands")
     (description
      "This package provides wrappers for the commands of Python@tie{}3.x such
@@ -966,14 +967,13 @@ datetime module, available in Python 2.3+.")
 (define-public python-pandas
   (package
     (name "python-pandas")
-    (version "0.16.0")
+    (version "0.16.2")
     (source
      (origin
-      (method url-fetch)
-      (uri (string-append "https://pypi.python.org/packages/source/p/"
-                          "pandas/pandas-" version ".tar.gz"))
-      (sha256
-       (base32 "1wfrp8dx1zcsry6f09ndza6qm1yr7f163211f4l9vjlnhxpxw4s0"))))
+       (method url-fetch)
+       (uri (pypi-uri "pandas" version))
+       (sha256
+        (base32 "10agmrkps8bi5948vwpipfxds5kj1d076m9i0nhaxwqiw7gm6670"))))
     (build-system python-build-system)
     (arguments
      `(;; Three tests fail:
@@ -1301,18 +1301,15 @@ bug tracker.")
 (define-public python-enum34
   (package
     (name "python-enum34")
-    (version "1.0")
+    (version "1.1.0")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "https://pypi.python.org/packages/source/e/"
-                          "enum34/enum34-" version ".tar.gz"))
+      (uri (pypi-uri "enum34" version))
       (sha256
        (base32
-        "0dg6mpg9n4g9diyrbnbb5vd9d1qw9f265zwhknqy0mxh0cvmjjrq"))))
+        "0yx1m4564wxgbm4glb3457hi16xihd9w63rv13y2przkdir9dfgp"))))
     (build-system python-build-system)
-    (inputs
-     `(("python-setuptools" ,python-setuptools)))
     (arguments
      `(#:phases
        (alist-replace
@@ -1326,6 +1323,9 @@ bug tracker.")
 backported for previous versions of Python from 2.4 to 3.3.")
     (license bsd-3)))
 
+(define-public python2-enum34
+  (package-with-python2 python-enum34))
+
 (define-public python-parse-type
   (package
     (name "python-parse-type")
@@ -1342,8 +1342,7 @@ backported for previous versions of Python from 2.4 to 3.3.")
     (inputs
      `(("python-setuptools" ,python-setuptools)
        ("python-six" ,python-six)
-       ("python-parse" ,python-parse)
-       ("python-enum34" ,python-enum34))) ;required for python<3.4
+       ("python-parse" ,python-parse)))
     (arguments '(#:tests? #f))            ;TODO: tests require pytest
     (home-page "https://github.com/jenisys/parse_type")
     (synopsis "Extended parse module")
@@ -1655,6 +1654,42 @@ supports coverage of subprocesses.")
 (define-public python2-pytest-runner
   (package-with-python2 python-pytest-runner))
 
+(define-public python-pytest-xdist
+  (package
+    (name "python-pytest-xdist")
+    (version "1.14")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "pytest-xdist" version ".zip"))
+       (sha256
+        (base32
+         "08rn2l39ds60xshs4js787l84pfckksqklfq2wq9x8ig2aci2pja"))))
+    (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)
+       ("python-pytest" ,python-pytest)
+       ("python-py" ,python-py)))
+    (home-page
+     "https://github.com/pytest-dev/pytest-xdist")
+    (synopsis
+     "Plugin for py.test with distributed testing and loop-on-failing modes")
+    (description
+     "The pytest-xdist plugin extends py.test with some unique test execution
+modes: parallelization, running tests in boxed subprocesses, the ability
+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)))
+
+(define-public python2-pytest-xdist
+  (package-with-python2 python-pytest-xdist))
+
 (define-public python-scripttest
   (package
     (name "python-scripttest")
@@ -1993,7 +2028,6 @@ backported from Python 2.7 for Python 2.4+.")
     (inputs
      `(("python-setuptools" ,python-setuptools)
        ("python-six" ,python-six)
-       ("python-enum43" ,python-enum34)
        ("python-parse" ,python-parse)
        ("python-parse-type" ,python-parse-type)))
     (arguments `(#:tests? #f))          ;TODO: tests require nose>=1.3 and
@@ -2107,14 +2141,14 @@ with sensible defaults out of the box.")
 (define-public python-wheel
   (package
     (name "python-wheel")
-    (version "0.26.0")
+    (version "0.29.0")
     (source
       (origin
         (method url-fetch)
         (uri (pypi-uri "wheel" version))
         (sha256
          (base32
-          "032k1ajijbqnv0z0k88bhf75mdimi18fcmm28mss90610lw3bbga"))))
+          "0j0n38hg1jvrmyy68f9ikvzq1gs9g0sx4ws7maf8wi3bwbbqmfqy"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)
@@ -2130,27 +2164,27 @@ packages will be properly installed with only the @code{Unpack} step and the
 unpacked archive preserves enough information to @code{Spread} (copy data and
 scripts to their final locations) at any later time.  Wheel files can be
 installed with a newer @code{pip} or with wheel's own command line utility.")
-    (license license:expat)))
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-wheel))))))
 
 (define-public python2-wheel
-  (let ((wheel (package-with-python2 python-wheel)))
+  (let ((wheel (package-with-python2
+                (strip-python2-variant python-wheel))))
     (package (inherit wheel)
-      (native-inputs
-       `(("python2-functools32" ,python2-functools32)
-         ("python2-jsonschema" ,python2-jsonschema)
-         ,@(alist-delete "python-jsonschema"
-                         (package-native-inputs wheel)))))))
+      (native-inputs `(("python2-functools32" ,python2-functools32)
+                        ,@(package-native-inputs wheel))))))
+
 
 (define-public python-requests
   (package
     (name "python-requests")
-    (version "2.8.1")
+    (version "2.9.1")
     (source (origin
              (method url-fetch)
              (uri (pypi-uri "requests" version))
              (sha256
               (base32
-               "0ny2nr1sqr4hcn3903ghmh7w2yni8shlfv240a8c9p6wyidqvzl4"))))
+               "0zsqrzlybf25xscgi7ja4s48y2abf9wvjkn47wh984qgs1fq2xy5"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
@@ -2179,12 +2213,7 @@ than Python’s urllib2 library.")
                "0gdr9dxm24amxpbyqpbh3lbwxc2i42hnqv50sigx568qssv3v2ir"))))))
 
 (define-public python2-requests
-  (let ((requests (package-with-python2 python-requests)))
-    (package (inherit requests)
-      (propagated-inputs
-       `(("python2-wheel" ,python2-wheel)
-         ,@(alist-delete "python-wheel"
-                         (package-propagated-inputs requests)))))))
+  (package-with-python2 python-requests))
 
 (define-public python-vcversioner
   (package
@@ -2231,10 +2260,12 @@ version numbers.")
     (synopsis "Implementation of JSON Schema for Python")
     (description
      "Jsonschema is an implementation of JSON Schema for Python.")
-    (license license:expat)))
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-jsonschema))))))
 
 (define-public python2-jsonschema
-  (let ((jsonschema (package-with-python2 python-jsonschema)))
+  (let ((jsonschema (package-with-python2
+                     (strip-python2-variant python-jsonschema))))
     (package (inherit jsonschema)
       (inputs
        `(("python2-functools32" ,python2-functools32)
@@ -2305,7 +2336,7 @@ somewhat intelligeble.")
     (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
@@ -2945,7 +2976,7 @@ writing C extensions for Python as easy as Python itself.")
 (define python-numpy-bootstrap
   (package
     (name "python-numpy-bootstrap")
-    (version "1.9.1")
+    (version "1.10.4")
     (source
      (origin
        (method url-fetch)
@@ -2953,7 +2984,7 @@ writing C extensions for Python as easy as Python itself.")
                            "/numpy-" version ".tar.gz"))
        (sha256
         (base32
-         "070ybfvpgfmiz2hs94x445hvkh9dh52nyi0m8jp5kdihgvhbnx80"))))
+         "1bjjhvncraka5s6i4lg644jrxij6bvycxy7an20gcz3a0m11iygp"))))
     (build-system python-build-system)
     (inputs
      `(("python-nose" ,python-nose)
@@ -3014,16 +3045,14 @@ capabilities.")
 (define-public python2-fastlmm
   (package
     (name "python2-fastlmm")
-    (version "0.2.14")
+    (version "0.2.21")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/f/fastlmm"
-             "/fastlmm-" version ".zip"))
+       (uri (pypi-uri "fastlmm" version ".zip"))
        (sha256
         (base32
-         "023sydkrc3yxad2bycar02jfswwlh4199kafzhf2bssyx2c3xa0l"))))
+         "1q8c34rpmwkfy3r4d5172pzdkpfryj561897z9r3x22gq7813x1m"))))
     (build-system python-build-system)
     (arguments
      `(#:python ,python-2)) ; only Python 2.7 is supported
@@ -3371,16 +3400,14 @@ toolkits.")
 (define-public python2-pysnptools
   (package
     (name "python2-pysnptools")
-    (version "0.2.13")
+    (version "0.3.5")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/p/pysnptools"
-             "/pysnptools-" version ".zip"))
+       (uri (pypi-uri "pysnptools" version ".zip"))
        (sha256
         (base32
-         "1rzf5qvwfvd2pp84b14pb2gdvxdk5avnj7rb41ac8gndpkr9g6ib"))))
+         "15f4j4w5q603i7mlphb5r6mb1mn33pqg81595fpjp158140yqx7b"))))
     (build-system python-build-system)
     (arguments
      `(#:python ,python-2)) ; only Python 2.7 is supported
@@ -3538,7 +3565,7 @@ routines such as routines for numerical integration and optimization.")
 (define-public python-sqlalchemy
   (package
     (name "python-sqlalchemy")
-    (version "0.9.7")
+    (version "1.0.12")
     (source
      (origin
       (method url-fetch)
@@ -3546,7 +3573,7 @@ routines such as routines for numerical integration and optimization.")
                           "SQLAlchemy/SQLAlchemy-" version ".tar.gz"))
       (sha256
        (base32
-        "059ayifj5l08v6vv56anhyibyllscn10dlzr2fcw68gz1hfjdzsz"))))
+        "1l8qclhd0s90w3pvwhi5mjxdwr5j7gw7cjka2fx6f2vqmq7f4yb6"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-cython" ,python-cython) ;for c extensions
@@ -3570,6 +3597,42 @@ simple and Pythonic domain language.")
 (define-public python2-sqlalchemy
   (package-with-python2 python-sqlalchemy))
 
+(define-public python-alembic
+  (package
+    (name "python-alembic")
+    (version "0.8.4")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "alembic" version))
+       (sha256
+        (base32
+         "0jk23a852l3ybv7gfz81xzslyrnqnpjds5x15zd234y9rh9gq1w5"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-mock" ,python-mock)
+       ("python-pytest-cov" ,python-pytest-cov)))
+    (propagated-inputs
+     `(("python-sqlalchemy" ,python-sqlalchemy)
+       ("python-mako" ,python-mako)
+       ("python-editor" ,python-editor)))
+    (home-page "http://bitbucket.org/zzzeek/alembic")
+    (synopsis
+     "Database migration tool for SQLAlchemy")
+    (description
+     "Alembic is a lightweight database migration tool for usage with the
+SQLAlchemy Database Toolkit for Python.")
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-alembic))))))
+
+(define-public python2-alembic
+  (let ((alembic (package-with-python2
+                  (strip-python2-variant python-alembic))))
+    (package
+      (inherit alembic)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs alembic))))))
+
 (define-public python-distutils-extra
   (package
     (name "python-distutils-extra")
@@ -3888,18 +3951,18 @@ PNG, PostScript, PDF, and SVG file output.")
 (define-public python-decorator
   (package
     (name "python-decorator")
-    (version "4.0.6")
+    (version "4.0.9")
     (source
      (origin
        (method url-fetch)
        (uri (pypi-uri "decorator" version))
        (sha256
-        (base32 "1710cwsbwr8fkiq59w2min7rwgdz7ly51yz8l8yh1zbpfxcm8qhw"))))
+        (base32 "1a5vwhflfd9sh3rfb40xlyipldgdzfff6brman57hqv3661jw0lh"))))
     (build-system python-build-system)
     (arguments '(#:tests? #f)) ; no test target
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
-    (home-page "http://pypi.python.org/pypi/decorator/")
+    (home-page "https://pypi.python.org/pypi/decorator/")
     (synopsis "Python module to simplify usage of decorators")
     (description
       "The aim of the decorator module is to simplify the usage of decorators
@@ -4141,15 +4204,14 @@ standard library.")
 (define-public python-traitlets
   (package
     (name "python-traitlets")
-    (version "4.0.0")
+    (version "4.1.0")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "https://pypi.python.org/packages/source/t/"
-                           "traitlets/traitlets-" version ".tar.gz"))
+       (uri (pypi-uri "traitlets" version))
        (sha256
         (base32
-         "0fr3w2xwb46c591dp7zw02bgf4d21mjy9g6rhwc9bwd4ji50n50b"))))
+         "0nxgj8jxlm1kqf8cx2x7vjid05zdgbxpqhjbdl46r8njlpgkh3j4"))))
     (build-system python-build-system)
     (arguments
      `(#:phases
@@ -4159,7 +4221,8 @@ standard library.")
      `(("python-ipython-genutils" ,python-ipython-genutils)
        ("python-decorator" ,python-decorator)))
     (native-inputs
-     `(("python-nose" ,python-nose)))
+     `(("python-mock" ,python-mock)
+       ("python-nose" ,python-nose)))
     (home-page "http://ipython.org")
     (synopsis "Configuration system for Python applications")
     (description
@@ -4294,17 +4357,14 @@ computing.")
 (define-public python-isodate
   (package
     (name "python-isodate")
-    (version "0.5.1")
+    (version "0.5.4")
     (source
       (origin
         (method url-fetch)
-        (uri (string-append
-              "https://pypi.python.org/packages/source/i/isodate/isodate-"
-              version
-              ".tar.gz"))
+        (uri (pypi-uri "isodate" version))
         (sha256
           (base32
-            "1yqjn0is0p64cmk9xhq4hc6q06jk86d60kg2jws58d78q0qysami"))))
+            "0cafaiwixgpxwh9dsd28qb0dbzsj6xpxjdkyk30ns91ps10mq422"))))
     (build-system python-build-system)
     (inputs
       `(("python-setuptools" ,python-setuptools)))
@@ -4323,17 +4383,14 @@ ISO 8601 dates, time and duration.")
 (define-public python-html5lib
   (package
     (name "python-html5lib")
-    (version "1.0b3")
+    (version "1.0b8")
     (source
       (origin
         (method url-fetch)
-        (uri (string-append
-              "https://pypi.python.org/packages/source/h/html5lib/html5lib-"
-              version
-              ".tar.gz"))
+        (uri (pypi-uri "html5lib" version))
         (sha256
           (base32
-            "1l5i6xzckzx4hnh9qzv9q3kyhkgjx2hsi2k9srgci3qizjmvp6ln"))))
+            "1lknq5j3nh11xrl268ks76zaj0gyzh34v94n5vbf6dk8llzxdx0q"))))
     (build-system python-build-system)
     (propagated-inputs
       `(("python-six" ,python-six))) ; required to "import html5lib"
@@ -4395,7 +4452,7 @@ features useful for text console applications.")
      (origin
        (method url-fetch)
        (uri (string-append
-             "http://dbus.freedesktop.org/releases/dbus-python/dbus-python-"
+             "https://dbus.freedesktop.org/releases/dbus-python/dbus-python-"
              version ".tar.gz"))
        (sha256
         (base32 "1py62qir966lvdkngg0v8k1khsqxwk5m4s8nflpk1agk5f5nqb71"))))
@@ -4471,17 +4528,14 @@ translate the complete SQLite API into Python.")
 (define-public python-lxml
   (package
     (name "python-lxml")
-    (version "3.4.2")
+    (version "3.5.0")
     (source
       (origin
         (method url-fetch)
-        (uri (string-append
-              "https://pypi.python.org/packages/source/l/lxml/lxml-"
-              version
-              ".tar.gz"))
+        (uri (pypi-uri "lxml" version))
         (sha256
           (base32
-            "0pd23qz8vms1mgm41p96h4vac5y91igs4wr9640gnvxgk019kmf7"))))
+            "0y7m2s8ci6q642zl85y5axkj8z827l0vhjl532acb75hlkir77rl"))))
     (build-system python-build-system)
     (inputs
       `(("libxml2" ,libxml2)
@@ -4498,6 +4552,39 @@ libxml2 and libxslt.")
 (define-public python2-lxml
   (package-with-python2 python-lxml))
 
+;; beautifulsoup4 has a totally different namespace than 3.x,
+;; and pypi seems to put it under its own name, so I guess we should too
+(define-public python-beautifulsoup4
+  (package
+    (name "python-beautifulsoup4")
+    (version "4.4.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "beautifulsoup4" version))
+       (sha256
+        (base32
+         "1d36lc4pfkvl74fmzdib2nqnvknm0jddgf2n9yd7im150qyh3m47"))))
+    (build-system python-build-system)
+    (home-page
+     "http://www.crummy.com/software/BeautifulSoup/bs4/")
+    (synopsis
+     "Python screen-scraping library")
+    (description
+     "Beautiful Soup is a Python library designed for rapidly setting up
+screen-scraping projects.  It offers Pythonic idioms for navigating,
+searching, and modifying a parse tree, providing a toolkit for
+dissecting a document and extracting what you need.  It automatically
+converts incoming documents to Unicode and outgoing documents to UTF-8.")
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-beautifulsoup4))))))
+
+(define-public python2-beautifulsoup4
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-beautifulsoup4)))
+    (native-inputs `(("python2-setuptools" ,python2-setuptools)))))
+
 (define-public python2-pil
   (package
     (name "python2-pil")
@@ -4658,15 +4745,13 @@ interfaces in an easy and portable manner.")
 (define-public python-networkx
   (package
     (name "python-networkx")
-    (version "1.9.1")
+    (version "1.11")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append
-             "https://pypi.python.org/packages/source/n/networkx/networkx-"
-             version ".tar.gz"))
+       (uri (pypi-uri "networkx" version))
        (sha256
-        (base32 "0n8wy0yq1kmdq4wh68mlhwhkndvwzx48lg41a1z0sxxms0wfp033"))))
+        (base32 "1f74s56xb4ggixiq0vxyfxsfk8p20c7a099lpcf60izv1php03hd"))))
     (build-system python-build-system)
     ;; python-decorator is needed at runtime
     (propagated-inputs
@@ -4965,17 +5050,14 @@ applications.")
 (define-public python-pep8
   (package
     (name "python-pep8")
-    (version "1.6.2")
+    (version "1.7.0")
     (source
       (origin
         (method url-fetch)
-        (uri (string-append
-               "https://pypi.python.org/packages/source/p/pep8/pep8-"
-               version
-               ".tar.gz"))
+        (uri (pypi-uri "pep8" version))
         (sha256
           (base32
-            "1zybkcdw1sx84dvkfss96nhykqg9bc0cdpwpl4k9wlxm61bf7dxq"))))
+            "002rkl4lsn6x2mxmf8ar00l0m8i3mzrc6pnzz77blyksmpsxa4x1"))))
     (build-system python-build-system)
     (inputs
       `(("python-setuptools" ,python-setuptools)))
@@ -5016,20 +5098,19 @@ PEP 8.")
 (define-public python-mccabe
   (package
     (name "python-mccabe")
-    (version "0.3.1")
+    (version "0.4.0")
     (source
       (origin
         (method url-fetch)
-        (uri (string-append
-               "https://pypi.python.org/packages/source/m/mccabe/mccabe-"
-               version
-               ".tar.gz"))
+        (uri (pypi-uri "mccabe" version))
         (sha256
           (base32
-            "05ix3vdv5hjk4irl97n2n3c4g1vqvz7dbmkzs13f3bx97bxsczjz"))))
+            "0yr08a36h8lqlif10l4xcikbbig7q8f41gqywir7rrvnv3mi4aws"))))
     (build-system python-build-system)
     (inputs
-      `(("python-setuptools" ,python-setuptools)))
+      `(("python-pytest" ,python-pytest)
+        ("python-pytest-runner" ,python-pytest-runner)
+        ("python-setuptools" ,python-setuptools)))
     (home-page "https://github.com/flintwork/mccabe")
     (synopsis "McCabe checker, plugin for flake8")
     (description
@@ -5049,7 +5130,8 @@ complexity of Python source code.")
         (uri (pypi-uri "mccabe" version))
         (sha256
           (base32
-            "0fi4a81kr5bcv5p4xgibqr595hyj5dafkqgsmfk96mfy8w71fajs"))))))
+            "0fi4a81kr5bcv5p4xgibqr595hyj5dafkqgsmfk96mfy8w71fajs"))))
+    (inputs `(("python-setuptools" ,python-setuptools)))))
 
 (define-public python2-mccabe-0.2.1
   (package-with-python2 python-mccabe-0.2.1))
@@ -5095,19 +5177,19 @@ complexity of Python source code.")
 (define-public python-flake8
   (package
     (name "python-flake8")
-    (version "2.5.1")
+    (version "2.5.4")
     (source
       (origin
         (method url-fetch)
         (uri (pypi-uri "flake8" version))
         (sha256
           (base32
-            "00sn2g5ydriv5anbipcrprpv797kh4q8rfa75w3fc7v7n14fv2j4"))))
+            "0bs9cz4fr99r2rwig1b8jwaadl1nan7kgpdzqwj0bwbckwbmh7nc"))))
     (build-system python-build-system)
     (inputs
       `(("python-setuptools" ,python-setuptools)
-        ("python-pep8" ,python-pep8-1.5.7)
-        ("python-pyflakes" ,python-pyflakes-0.8.1)
+        ("python-pep8" ,python-pep8)
+        ("python-pyflakes" ,python-pyflakes)
         ("python-mccabe" ,python-mccabe)
         ("python-mock" ,python-mock)
         ("python-nose" ,python-nose)))
@@ -5314,7 +5396,7 @@ from an XML-based format.")
 (define-public python-ly
   (package
     (name "python-ly")
-    (version "0.9.2")
+    (version "0.9.3")
     (source
      (origin
        (method url-fetch)
@@ -5323,7 +5405,7 @@ from an XML-based format.")
              version ".tar.gz"))
        (sha256
         (base32
-         "1bsjg4q9ihr8bfdclrcmb8yjcg8xm9dznh58f3zsyrkrjzwbhcd2"))))
+         "1y6ananq8fia4y4m5id6gvsrm68bzpzd1y46pfzvawic0wjg2l0l"))))
     (build-system python-build-system)
     (native-inputs
      `(("python-setuptools" ,python-setuptools)))
@@ -5790,7 +5872,6 @@ responses, rather than doing any computation.")
      `(("python-cffi" ,python-cffi)
        ("python-six" ,python-six)
        ("python-pyasn1" ,python-pyasn1)
-       ("python-enum34" ,python-enum34)
        ("python-idna" ,python-idna)
        ("python-iso8601" ,python-iso8601)))
     (native-inputs
@@ -5810,15 +5891,18 @@ library” for Python.  The package includes both high level recipes, and low
 level interfaces to common cryptographic algorithms such as symmetric ciphers,
 message digests and key derivation functions.")
     ;; Distributed under either BSD-3 or ASL2.0
-    (license (list bsd-3 asl2.0))))
+    (license (list bsd-3 asl2.0))
+    (properties `((python2-variant . ,(delay python2-cryptography))))))
 
 (define-public python2-cryptography
-  (let ((crypto (package-with-python2 python-cryptography)))
+  (let ((crypto (package-with-python2
+                 (strip-python2-variant python-cryptography))))
     (package (inherit crypto)
       (propagated-inputs
        `(("python2-ipaddress" ,python2-ipaddress)
          ("python2-backport-ssl-match-hostname"
           ,python2-backport-ssl-match-hostname)
+         ("python2-enum34" ,python2-enum34)
          ,@(package-propagated-inputs crypto))))))
 
 (define-public python-pyopenssl
@@ -5870,12 +5954,7 @@ library.")
     (license asl2.0)))
 
 (define-public python2-pyopenssl
-  (let ((pyopenssl (package-with-python2 python-pyopenssl)))
-    (package (inherit pyopenssl)
-      (propagated-inputs
-       `(("python2-cryptography" ,python2-cryptography)
-         ,@(alist-delete "python-cryptography"
-                         (package-propagated-inputs pyopenssl)))))))
+  (package-with-python2 python-pyopenssl))
 
 (define-public python-pip
   (package
@@ -6663,7 +6742,7 @@ of the SSL peer.")
          (replace 'check
            (lambda _ (zero?
                       (system*
-                       "python" "test_contextlib2.py", "-v")))))))
+                       "python" "test_contextlib2.py" "-v")))))))
     (home-page "http://contextlib2.readthedocs.org/")
     (synopsis "Tools for decorators and context managers")
     (description "This module is primarily a backport of the Python
@@ -6728,13 +6807,13 @@ WebSocket usage in Python programs.")
 (define-public python-atomicwrites
   (package
     (name "python-atomicwrites")
-    (version "0.1.8")
+    (version "0.1.9")
     (source (origin
              (method url-fetch)
              (uri (pypi-uri "atomicwrites" version))
              (sha256
               (base32
-               "13nwk0gw0yb61pnf5vxs3fvhav6q3zrf08x9ggc93bnk5fsssx1j"))))
+               "08s05h211r07vs66r4din3swrbzb344vli041fihpg34q3lcxpvw"))))
     (build-system python-build-system)
     (synopsis "Atomic file writes in Python")
     (description "Library for atomic file writes using platform dependent tools
@@ -6745,13 +6824,13 @@ for atomic filesystem operations.")
 (define-public python-requests-toolbelt
   (package
     (name "python-requests-toolbelt")
-    (version "0.5.0")
+    (version "0.6.0")
     (source (origin
              (method url-fetch)
              (uri (pypi-uri "requests-toolbelt" version))
              (sha256
               (base32
-               "1kbms1s52dhb98vbpaprr15b0ijdbqp500lpfsyjccpd8cjkyngk"))))
+               "07slish560haspn0hpwgy2izhk2snqq06s6acp8xzmhhz079qknc"))))
     (build-system python-build-system)
     (propagated-inputs
      `(("python-requests" ,python-requests)))
@@ -6783,13 +6862,13 @@ applications.")
 (define-public python-click-log
   (package
     (name "python-click-log")
-    (version "0.1.1")
+    (version "0.1.3")
     (source (origin
              (method url-fetch)
              (uri (pypi-uri "click-log" version))
              (sha256
               (base32
-               "1z3jdwjmwax159zrnyx830xa968rfqrpkm04ad5xqyh0269ydiqb"))))
+               "0kdd1vminxpcfczxl2kkf285n0dr1gxh2cdbx1p6vkj7b7bci3gx"))))
     (build-system python-build-system)
     (propagated-inputs
      `(("python-click" ,python-click)))
@@ -6810,8 +6889,6 @@ applications.")
               (base32
                "1iks5701qnp3dlr3q1d9qm68y2plp2m029irhpz92a44psfkjf1f"))))
     (build-system python-build-system)
-    (native-inputs
-     `(("unzip" ,unzip)))
     (propagated-inputs
      `(("python-pytest" ,python-pytest)))
     (synopsis "Namespace control and lazy-import mechanism")
@@ -6819,7 +6896,15 @@ applications.")
 package and greatly reduce the number of imports for your users.  It is a small
 pure Python module that works on virtually all Python versions.")
     (home-page "https://bitbucket.org/hpk42/apipkg")
-    (license license:expat)))
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-apipkg))))))
+
+(define-public python2-apipkg
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-apipkg)))
+    (native-inputs
+     `(("python2-setuptools" ,python2-setuptools)))))
 
 (define-public python-execnet
   (package
@@ -6847,7 +6932,17 @@ minimal and fast API targetting the following uses:
 @item write scripts to administer multiple environments
 @end enumerate")
     (home-page "http://codespeak.net/execnet/")
-    (license license:expat)))
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-execnet))))))
+
+(define-public python2-execnet
+  (let ((execnet (package-with-python2
+                  (strip-python2-variant python-execnet))))
+    (package
+      (inherit execnet)
+      (native-inputs
+       `(("python2-setuptools" ,python2-setuptools)
+         ,@(package-native-inputs execnet))))))
 
 ;;; The software provided by this package was integrated into pytest 2.8.
 (define-public python-pytest-cache
@@ -6872,13 +6967,13 @@ the last py.test invocation.")
 (define-public python-pytest-localserver
   (package
     (name "python-pytest-localserver")
-    (version "0.3.4")
+    (version "0.3.5")
     (source (origin
              (method url-fetch)
-             (uri (pypi-uri "pytest-localserver" version ".zip"))
+             (uri (pypi-uri "pytest-localserver" version))
              (sha256
               (base32
-               "050q505a7gnsz7vqidw0w5dvxjb2flzi7z734agpjzmsl85c2bcx"))))
+               "0dvqspjr6va55zwmnnc2mmpqc7mm65kxig9ya44x1z8aadzxpa4p"))))
     (build-system python-build-system)
     (arguments
       `(#:phases (modify-phases %standard-phases
@@ -6902,16 +6997,17 @@ framework which enables you to test server connections locally.")
 (define-public python-wsgi-intercept
   (package
     (name "python-wsgi-intercept")
-    (version "0.10.3")
+    (version "1.1.2")
     (source (origin
              (method url-fetch)
              (uri (pypi-uri "wsgi_intercept" version))
              (sha256
               (base32
-               "0xyfchacywb1mql84270mcidsqc5ssyspd18yacjk82x2xc68h0r"))))
+               "14ajy415ch5d0dnspg4b592p66wlgzah7ay218flp13517fp49zl"))))
     (build-system python-build-system)
     (native-inputs
-     `(("python-pytest" ,python-pytest)))
+     `(("python-pytest" ,python-pytest)
+       ("python-six" ,python-six)))
     (propagated-inputs
      `(("python-httplib2" ,python-httplib2)
        ("python-requests" ,python-requests)))
@@ -7140,7 +7236,7 @@ authenticated session objects providing things like keep-alive.")
     (package (inherit rauth)
       (propagated-inputs `(("python2-requests" ,python2-requests)))
       (native-inputs
-       `(("python2-unittest2", python2-unittest2)
+       `(("python2-unittest2" ,python2-unittest2)
          ,@(package-native-inputs rauth))))))
 
 (define-public python2-functools32
@@ -7424,17 +7520,14 @@ Amazon Web Services (AWS) API.")
 (define-public python-hypothesis
   (package
     (name "python-hypothesis")
-    (version "2.0.0")
+    (version "3.0.4")
     (source (origin
               (method url-fetch)
               (uri (pypi-uri "hypothesis" version))
               (sha256
                (base32
-                "1la6mfpvcn640gs2v35iv8b4sh6xdhp9j5ghay0jd86c9n4fkgxr"))))
+                "0bh6pqyc56cqlbpg0ffzjs6466blyylix4nsw11qrqwf01cg9gdq"))))
     (build-system python-build-system)
-    (native-inputs
-     `(;; setuptools required for python-2 variant
-       ("python-setuptools" ,python-setuptools)))
     (propagated-inputs
      `(("python-flake8" ,python-flake8)
        ("python-pytest" ,python-pytest)))
@@ -7444,10 +7537,16 @@ much larger range of examples than you would ever want to write by hand.  It’s
 based on the Haskell library, Quickcheck, and is designed to integrate
 seamlessly into your existing Python unit testing work flow.")
     (home-page "https://github.com/DRMacIver/hypothesis")
-    (license mpl2.0)))
+    (license mpl2.0)
+    (properties `((python2-variant . ,(delay python2-hypothesis))))))
 
 (define-public python2-hypothesis
-  (package-with-python2 python-hypothesis))
+  (let ((hypothesis (package-with-python2
+                     (strip-python2-variant python-hypothesis))))
+    (package (inherit hypothesis)
+      (native-inputs
+       `(("python2-enum34" ,python2-enum34)
+         ("python2-setuptools" ,python2-setuptools))))))
 
 (define-public python-pytest-subtesthack
   (package
@@ -7503,3 +7602,657 @@ input.  (Note that this is mostly a legacy library; you may wish to look at
 python-xdo for newer bindings.)")
     (license bsd-3)))
 
+(define-public python-wtforms
+  (package
+    (name "python-wtforms")
+    (version "2.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "WTForms" version ".zip"))
+       (sha256
+        (base32
+         "0vyl26y9cg409cfyj8rhqxazsdnd0jipgjw06civhrd53yyi1pzz"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("unzip" ,unzip)))
+    (home-page "http://wtforms.simplecodes.com/")
+    (synopsis
+     "Form validation and rendering library for Python web development")
+    (description
+     "WTForms is a flexible forms validation and rendering library
+for Python web development.  It is very similar to the web form API
+available in Django, but is a standalone package.")
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-wtforms))))))
+
+(define-public python2-wtforms
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-wtforms)))
+    (inputs `(("python2-setuptools" ,python2-setuptools)))))
+
+(define-public python-mako
+  (package
+    (name "python-mako")
+    (version "1.0.3")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "Mako" version))
+       (sha256
+        (base32
+         "136kcjbs0s98qkx8a418b05dfblqp0kiiqyx8vhx4rarwc7bqi3n"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-markupsafe" ,python-markupsafe)
+       ("python-mock" ,python-mock)
+       ("python-nose" ,python-nose)))
+    (home-page "http://www.makotemplates.org/")
+    (synopsis "Templating language for Python")
+    (description "Mako is a templating language for Python that compiles
+templates into Python modules.")
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-mako))))))
+
+(define-public python2-mako
+  (let ((base (package-with-python2
+               (strip-python2-variant python-mako))))
+    (package
+      (inherit base)
+      (native-inputs
+       (cons `("python2-setuptools" ,python2-setuptools)
+             (package-native-inputs base))))))
+
+(define-public python-waitress
+  (package
+    (name "python-waitress")
+    (version "0.8.10")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "waitress" version))
+       (sha256
+        (base32
+         "017n9ra6vvmq9d5sfhdzyzr1mg15x2hj2dhm4pdlw98c1ypw2h3w"))))
+    (build-system python-build-system)
+    (home-page "https://github.com/Pylons/waitress")
+    (synopsis "Waitress WSGI server")
+    (description "Waitress is meant to be a production-quality pure-Python WSGI
+server with very acceptable performance.")
+    (license zpl2.1)
+    (properties `((python2-variant . ,(delay python2-waitress))))))
+
+(define-public python2-waitress
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-waitress)))
+    (native-inputs `(("python2-setuptools" ,python2-setuptools)))))
+
+(define-public python-wsgiproxy2
+  (package
+    (name "python-wsgiproxy2")
+    (version "0.4.2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "WSGIProxy2" version ".zip"))
+       (sha256
+        (base32
+         "13kf9bdxrc95y9vriaz0viry3ah11nz4rlrykcfvb8nlqpx3dcm4"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("unzip" ,unzip)
+       ("python-nose" ,python-nose)
+       ("python-coverage" ,python-coverage)))
+    (propagated-inputs
+     `(("python-six" ,python-six)
+       ("python-webob" ,python-webob)))
+    (home-page
+     "https://github.com/gawel/WSGIProxy2/")
+    (synopsis "WSGI Proxy with various http client backends")
+    (description "WSGI turns HTTP requests into WSGI function calls.
+WSGIProxy turns WSGI function calls into HTTP requests.
+It also includes code to sign requests and pass private data,
+and to spawn subprocesses to handle requests.")
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-wsgiproxy2))))))
+
+(define-public python2-wsgiproxy2
+  (let ((wsgiproxy2 (package-with-python2
+                     (strip-python2-variant python-wsgiproxy2))))
+    (package
+      (inherit wsgiproxy2)
+      (inputs `(("python2-setuptools" ,python2-setuptools)
+                ,@(package-inputs wsgiproxy2))))))
+
+(define-public python-pastedeploy
+  (package
+    (name "python-pastedeploy")
+    (version "1.5.2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "PasteDeploy" version))
+       (sha256
+        (base32
+         "1jz3m4hq8v6hyhfjz9425nd3nvn52cvbfipdcd72krjmla4qz1fm"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-nose" ,python-nose)))
+    (propagated-inputs
+     ;; This package uses pkg_resources, part of setuptools, during runtime,
+     ;; hence why not a native-input.
+     `(("python-setuptools" ,python-setuptools)))
+    (home-page "http://pythonpaste.org/deploy/")
+    (synopsis
+     "Load, configure, and compose WSGI applications and servers")
+    (description
+     "This tool provides code to load WSGI applications and servers from URIs;
+these URIs can refer to Python Eggs for INI-style configuration files.  Paste
+Script provides commands to serve applications based on this configuration
+file.")
+    (license license:expat)))
+
+(define-public python2-pastedeploy
+  (package-with-python2 python-pastedeploy))
+
+(define-public python-paste
+  (package
+    (name "python-paste")
+    (version "2.0.2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "Paste" version))
+       (sha256
+        (base32
+         "16dsv9qi0r4qsrsb6dilpq2rx0fnglvh36flzywcdnm2jg43mb5d"))
+       (patches (list (search-patch
+                       "python-paste-remove-website-test.patch")
+                      (search-patch
+                       "python-paste-remove-timing-test.patch")))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-nose" ,python-nose)))
+    (propagated-inputs
+     `(;; Uses pkg_resources provided by setuptools internally.
+       ("python-setuptools" ,python-setuptools)
+       ("python-six" ,python-six)))
+    (arguments
+     '(;; Tests don't pass on Python 3, but work fine on Python 2.
+       ;; (As of 2.0.2, Python 3 support in Paste is presently a bit broken,
+       ;; but is usable enough for the minimal amount it's used in MediaGoblin
+       ;; still... things should be better by the next Paste release.)
+       #:tests? #f))
+    (home-page "http://pythonpaste.org")
+    (synopsis
+     "Python web development tools, focusing on WSGI")
+    (description
+     "Paste provides a variety of web development tools and middleware which
+can be nested together to build web applications.  Paste's design closely
+follows ideas flowing from WSGI (Web Standard Gateway Interface).")
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-paste))))))
+
+(define-public python2-paste
+  (let ((paste (package-with-python2
+                (strip-python2-variant python-paste))))
+    (package
+      (inherit paste)
+      (arguments
+       ;; Tests are back for Python 2!
+       `(#:tests? #t
+         ,@(package-arguments paste))))))
+
+(define-public python-pastescript
+  (package
+    (name "python-pastescript")
+    (version "2.0.2")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "PasteScript" version))
+       (sha256
+        (base32
+         "1h3nnhn45kf4pbcv669ik4faw04j58k8vbj1hwrc532k0nc28gy0"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-nose" ,python-nose)))
+    (propagated-inputs
+     `(;; Uses pkg_resources provided by setuptools internally.
+       ("python-setuptools" ,python-setuptools)
+       ("python-paste" ,python-paste)
+       ("python-pastedeploy" ,python-pastedeploy)))
+    (home-page "http://pythonpaste.org/script/")
+    (arguments
+     '(;; Unfortunately, this requires the latest unittest2,
+       ;; but that requires traceback2 which requires linecache2 which requires
+       ;; unittest2.  So we're skipping tests for now.
+       ;; (Note: Apparently linetest2 only needs unittest2 for its tests,
+       ;; so in theory we could get around this situation somehow.)
+       #:tests? #f))
+    (synopsis
+     "Pluggable command line tool for serving web applications and more")
+    (description
+     "PasteScript is a plugin-friendly command line tool which provides a
+variety of features, from launching web applications to bootstrapping project
+layouts.")
+    (license license:expat)))
+
+(define-public python2-pastescript
+  (package-with-python2 python-pastescript))
+
+(define-public python-pyquery
+  (package
+    (name "python-pyquery")
+    (version "1.2.11")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "pyquery" version))
+       (sha256
+        (base32
+         "1ikz1387nsp0pp7mzzr6ip9n5gr67acpap24yn33987v7fkjp0sa"))))
+    (build-system python-build-system)
+    (propagated-inputs
+     `(("python-lxml" ,python-lxml)
+       ("python-cssselect" ,python-cssselect)))
+    (home-page "https://github.com/gawel/pyquery")
+    (synopsis "Make jQuery-like queries on xml documents")
+    (description "pyquery allows you to make jQuery queries on xml documents.
+The API is as much as possible the similar to jQuery.  pyquery uses lxml for
+fast xml and html manipulation.")
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-pyquery))))))
+
+(define-public python2-pyquery
+  (let ((pyquery (package-with-python2
+                  (strip-python2-variant python-pyquery))))
+    (package
+      (inherit pyquery)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools))))))
+
+(define-public python-webtest
+  (package
+    (name "python-webtest")
+    (version "2.0.20")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "WebTest" version))
+       (sha256
+        (base32
+         "0bv0qhdjakdsdgj4sk21gnpp8xp8bga4x03p6gjb83ihrsb7n4xv"))))
+    (build-system python-build-system)
+    (arguments
+     `(;; Unfortunately we have to disable tests!
+       ;; This release of WebTest is pinned to python-nose < 1.3,
+       ;; but older versions of python-nose are plagued with the following
+       ;; bug(s), which rears its ugly head during test execution:
+       ;;   https://github.com/nose-devs/nose/issues/759
+       ;;   https://github.com/nose-devs/nose/pull/811
+       #:tests? #f))
+    ;; Commented out code is no good, but in this case, once tests
+    ;; are ready to be enabled again, we should put the following
+    ;; in place:
+    ;;  (native-inputs
+    ;;   `(("python-nose" ,python-nose) ; technially < 1.3,
+    ;;                                  ; but see above comment
+    ;;     ("python-coverage" ,python-coverage)
+    ;;     ("python-mock" ,python-mock)
+    ;;     ("python-pastedeploy" ,python-pastedeploy)
+    ;;     ("python-wsgiproxy2" ,python-wsgiproxy2)
+    ;;     ("python-pyquery" ,python-pyquery)))
+    (propagated-inputs
+     `(("python-waitress" ,python-waitress)
+       ("python-webob" ,python-webob)
+       ("python-six" ,python-six)
+       ("python-beautifulsoup4" ,python-beautifulsoup4)))
+    (home-page "http://webtest.pythonpaste.org/")
+    (synopsis "Helper to test WSGI applications")
+    (description "Webtest allows you to test your Python web applications
+without starting an HTTP server.  It supports anything that supports the
+minimum of WSGI.")
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-webtest))))))
+
+(define-public python2-webtest
+  (let ((webtest (package-with-python2
+                  (strip-python2-variant python-webtest))))
+    (package
+      (inherit webtest)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs webtest))))))
+
+(define-public python-anyjson
+  (package
+    (name "python-anyjson")
+    (version "0.3.3")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "anyjson" version))
+       (sha256
+        (base32
+         "1fjph4alvcscsl5d4b6qpv1yh31jy05jxi1l0xff7lws7j32v09p"))))
+    (build-system python-build-system)
+    (arguments
+     `(;; We could possibly get tests working, but on Python 3 it's not so easy.
+       ;; Very strangely, 2to3 is run *during setup.py install* (or bdist, or
+       ;; whatever) so this transformation needs to be done before the tests
+       ;; can be run.  Maybe we could add a build step to transform beforehand
+       ;; but it could be annoying/difficult.
+       ;; We can enable tests for the Python 2 version, though, and do below.
+       #:tests? #f))
+    (home-page "http://bitbucket.org/runeh/anyjson/")
+    (synopsis
+     "Wraps best available JSON implementation in a common interface")
+    (description
+     "Anyjson loads whichever is the fastest JSON module installed
+and provides a uniform API regardless of which JSON implementation is used.")
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-anyjson))))))
+
+(define-public python2-anyjson
+  (let ((anyjson (package-with-python2
+                  (strip-python2-variant python-anyjson))))
+    (package
+      (inherit anyjson)
+      (arguments `(;; Unlike the python 3 variant, we do run tests.  See above!
+                   #:tests? #t
+                   ,@(package-arguments anyjson)))
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ("python2-nose" ,python2-nose))))))
+
+(define-public python-amqp
+  (package
+    (name "python-amqp")
+    (version "1.4.9")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "amqp" version))
+       (sha256
+        (base32
+         "06n6q0kxhjnbfz3vn8x9yz09lwmn1xi9d6wxp31h5jbks0b4vsid"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-nose" ,python-nose)
+       ("python-mock" ,python-mock)))
+    (home-page "http://github.com/celery/py-amqp")
+    (synopsis
+     "Low-level AMQP client for Python (fork of amqplib)")
+    (description
+     "This is a fork of amqplib which was originally written by Barry Pederson.
+It is maintained by the Celery project, and used by kombu as a pure python
+alternative when librabbitmq is not available.")
+    (license lgpl2.1+)
+    (properties `((python2-variant . ,(delay python2-amqp))))))
+
+(define-public python2-amqp
+  (let ((amqp (package-with-python2
+               (strip-python2-variant python-amqp))))
+    (package
+      (inherit amqp)
+      (arguments `(;; Tries to run coverage tests with nose-cover3, which seems
+                   ;; unmaintained.  Weirdly, does not do this on the python 3
+                   ;; version?
+                   #:tests? #f
+                   ,@(package-arguments amqp)))
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ,@(package-native-inputs amqp))))))
+
+(define-public python-kombu
+  (package
+    (name "python-kombu")
+    (version "3.0.33")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "kombu" version))
+       (sha256
+        (base32
+         "16brjx2lgwbj2a37d0pjbfb84nvld6irghmqrs3qfncajp51hgc5"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-mock" ,python-mock)
+       ("python-nose" ,python-nose)))
+    (propagated-inputs
+     `(("python-anyjson" ,python-anyjson)
+       ("python-amqp" ,python-amqp)))
+    (home-page "http://kombu.readthedocs.org")
+    (synopsis "Message passing library for Python")
+    (description "The aim of Kombu is to make messaging in Python as easy as
+possible by providing an idiomatic high-level interface for the AMQ protocol,
+and also provide proven and tested solutions to common messaging problems.
+AMQP is the Advanced Message Queuing Protocol, an open standard protocol for
+message orientation, queuing, routing, reliability and security, for which the
+RabbitMQ messaging server is the most popular implementation.")
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-kombu))))))
+
+(define-public python2-kombu
+  (let ((kombu (package-with-python2
+                (strip-python2-variant python-kombu))))
+    (package
+      (inherit kombu)
+      (inputs `(("python2-setuptools" ,python2-setuptools)
+                ("python2-unittest2" ,python2-unittest2)
+                ,@(package-inputs kombu))))))
+
+(define-public python-billiard
+  (package
+    (name "python-billiard")
+    (version "3.3.0.22")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "billiard" version))
+       (sha256
+        (base32
+         "0zp7h6a58alrb3mwdw61jds07395j4j0mj6iqsb8czrihw9ih5nj"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-nose" ,python-nose)))
+    (home-page "http://github.com/celery/billiard")
+    (synopsis
+     "Python multiprocessing fork with improvements and bugfixes")
+    (description
+     "Billiard is a fork of the Python 2.7 multiprocessing package.  The
+multiprocessing package itself is a renamed and updated version of R Oudkerk's
+pyprocessing package.  This standalone variant is intended to be compatible with
+Python 2.4 and 2.5, and will draw its fixes/improvements from python-trunk.")
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-billiard))))))
+
+(define-public python2-billiard
+  (let ((billiard (package-with-python2
+                   (strip-python2-variant python-billiard))))
+    (package
+      (inherit billiard)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ("python2-unittest2" ,python2-unittest2)
+                       ("python2-mock" ,python2-mock)
+                       ,@(package-native-inputs billiard))))))
+
+(define-public python-celery
+  (package
+    (name "python-celery")
+    (version "3.1.20")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "celery" version))
+       (sha256
+        (base32
+         "1md6ywg1s0946qyp8ndnsd677wm0yax933h2sb4m3a4j7lf1jbyh"))))
+    (build-system python-build-system)
+    (native-inputs
+     `(("python-nose" ,python-nose)))
+    (propagated-inputs
+     `(("python-pytz" ,python-pytz)
+       ("python-billiard" ,python-billiard)
+       ("python-kombu" ,python-kombu)))
+    (home-page "http://celeryproject.org")
+    (synopsis "Distributed Task Queue")
+    (description "Celery is an asynchronous task queue/job queue based on
+distributed message passing.  It is focused on real-time operation, but
+supports scheduling as well.  The execution units, called tasks, are executed
+concurrently on a single or more worker servers using multiprocessing,
+Eventlet, or gevent.  Tasks can execute asynchronously (in the background) or
+synchronously (wait until ready).")
+    (license bsd-3)
+    (properties `((python2-variant . ,(delay python2-celery))))))
+
+(define-public python2-celery
+  (let ((celery (package-with-python2
+                 (strip-python2-variant python-celery))))
+    (package
+      (inherit celery)
+      (native-inputs `(("python2-setuptools" ,python2-setuptools)
+                       ("python2-unittest2" ,python2-unittest2)
+                       ("python2-mock" ,python2-mock)
+                       ,@(package-native-inputs celery))))))
+
+(define-public python-translitcodec
+  (package
+    (name "python-translitcodec")
+    (version "0.4.0")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "translitcodec" version))
+       (sha256
+        (base32
+         "10x6pvblkzky1zhjs8nmx64nb9jdzxad4bxhq4iwv0j4z2aqjnki"))))
+    (build-system python-build-system)
+    (arguments
+     `(#:tests? #f))  ; no tests provided
+    (home-page
+     "https://github.com/claudep/translitcodec")
+    (synopsis
+     "Unicode to 8-bit charset transliteration codec")
+    (description
+     "This package contains codecs for transliterating ISO 10646 texts into
+best-effort representations using smaller coded character sets (ASCII,
+ISO 8859, etc.).")
+    (license license:expat)
+    (properties `((python2-variant . ,(delay python2-translitcodec))))))
+
+(define-public python2-translitcodec
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-translitcodec)))
+    (native-inputs `(("python2-setuptools" ,python2-setuptools)))))
+
+(define-public python-editor
+  (package
+  (name "python-editor")
+  (version "0.5")
+  (source
+    (origin
+      (method url-fetch)
+      (uri (pypi-uri "python-editor" version))
+      (sha256
+        (base32
+          "1ypnpgvzpkbwsg4rdvy4sy51j28b5xq9v8pnkwxncn07vqz06p7n"))))
+  (build-system python-build-system)
+  (home-page
+    "https://github.com/fmoo/python-editor")
+  (synopsis
+    "Programmatically open an editor, capture the result")
+  (description
+    "python-editor is a library that provides the editor module for
+programmatically interfacing with your system's $EDITOR.")
+  (license asl2.0)
+  (properties `((python2-variant . ,(delay python2-editor))))))
+
+(define-public python2-editor
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-editor)))
+    (inputs `(("python2-setuptools" ,python2-setuptools)))))
+
+(define-public python-sphinxcontrib-programoutput
+  (package
+    (name "python-sphinxcontrib-programoutput")
+    (version "0.8")
+    (source (origin
+              (method url-fetch)
+              (uri (pypi-uri "sphinxcontrib-programoutput" version))
+              (sha256
+               (base32
+                "098as6z1s0gb4dh5xcr1fd2vpm91zj93jzvgawspxf5s4hqs0xhp"))))
+    (build-system python-build-system)
+    (propagated-inputs
+     `(("python-docutils" ,python-docutils)
+       ("python-sphinx" ,python-sphinx)))
+    (synopsis "Sphinx extension to include program output")
+    (description "A Sphinx extension to literally insert the output of arbitrary
+commands into documents, helping you to keep your command examples up to date.")
+    (home-page "https://github.com/lunaryorn/sphinxcontrib-programoutput")
+    (license bsd-2)
+    (properties `((python2-variant . ,(delay python2-sphinxcontrib-programoutput))))))
+
+(define-public python2-sphinxcontrib-programoutput
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-sphinxcontrib-programoutput)))
+    (native-inputs `(("python2-setuptools" ,python2-setuptools)))))
+
+(define-public python-sphinx-repoze-autointerface
+  (package
+    (name "python-sphinx-repoze-autointerface")
+    (version "0.7.1")
+    (source (origin
+              (method url-fetch)
+              (uri (pypi-uri "repoze.sphinx.autointerface" version))
+              (sha256
+               (base32
+                "016mv3wbylw278wl7z33y2liyra8ljp08zq1g0anzadh1an5zvwp"))))
+    (build-system python-build-system)
+    (propagated-inputs
+     `(("python-docutils" ,python-docutils)
+       ("python-sphinx" ,python-sphinx)
+       ("python-zope-interface" ,python-zope-interface)))
+    (synopsis "Auto-generate Sphinx API docs from Zope interfaces")
+    (description "This package defines an extension for the Sphinx documentation
+system.  The extension allows generation of API documentation by
+introspection of @code{zope.interface} instances in code.")
+    (home-page "https://github.com/repoze/repoze.sphinx.autointerface")
+    (license repoze)))
+
+(define-public python2-sphinx-repoze-autointerface
+  (package-with-python2 python-sphinx-repoze-autointerface))
+
+(define-public python-psycopg2
+  (package
+    (name "python-psycopg2")
+    (version "2.6.1")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (pypi-uri "psycopg2" version))
+       (sha256
+        (base32
+         "0k4hshvrwsh8yagydyxgmd0pjm29lwdxkngcq9fzfzkmpsxrmkva"))))
+    (build-system python-build-system)
+    (arguments
+     ;; Tests would require a postgresql database "psycopg2_test"
+     ;; and a running postgresql database management service.
+     `(#:tests? #f)) ; TODO re-enable after providing a test-db.
+    (inputs
+     `(("postgresql" ,postgresql))) ; libpq
+    (home-page "http://initd.org/psycopg/")
+    (synopsis "Python PostgreSQL adapter")
+    (description
+     "psycopg2 is a thread-safe PostgreSQL adapter that implements DB-API 2.0. ")
+    (license lgpl3+)
+    (properties `((python2-variant . ,(delay python2-psycopg2))))))
+
+(define-public python2-psycopg2
+  (package
+    (inherit (package-with-python2
+              (strip-python2-variant python-psycopg2)))
+    (native-inputs `(("python2-setuptools" ,python2-setuptools)))))
diff --git a/gnu/packages/qemu.scm b/gnu/packages/qemu.scm
index 7624cdcae9..1104a2da6a 100644
--- a/gnu/packages/qemu.scm
+++ b/gnu/packages/qemu.scm
@@ -71,7 +71,11 @@
                      "qemu-CVE-2015-8613.patch"
                      "qemu-CVE-2015-8701.patch"
                      "qemu-CVE-2015-8743.patch"
-                     "qemu-CVE-2016-1568.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 dccc9a2e48..bfd99b6519 100644
--- a/gnu/packages/qt.scm
+++ b/gnu/packages/qt.scm
@@ -20,7 +20,7 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu packages qt)
-  #:use-module ((guix licenses) #:select (bsd-3 gpl2 gpl3 lgpl2.1 x11-style))
+  #:use-module ((guix licenses) #:select (bsd-3 gpl2 gpl3 lgpl2.1 lgpl2.1+ x11-style))
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix build utils)
@@ -337,6 +337,30 @@ developers using C++ or QML, a CSS & JavaScript like language.")
               (delete-file-recursively olddoc)
               #t))))))))
 
+(define-public qjson
+  (package
+    (name "qjson")
+    (version "0.8.1")
+    (source (origin
+             (method url-fetch)
+             (uri (string-append "https://github.com/flavio/qjson/archive/"
+                                 version ".tar.gz"))
+             (file-name (string-append name "-" version ".tar.gz"))
+             (sha256
+              (base32
+               "163fspi0xc705irv79qw861fmh68pjyla9vx3kqiq6xrdhb9834j"))))
+    (build-system cmake-build-system)
+    (inputs
+     `(("qt" ,qt-4)))
+    (arguments
+     `(#:tests? #f)) ; no test target
+    (home-page "http://qjson.sourceforge.net/")
+    (synopsis "Qt-based library for handling JSON")
+    (description "QJson is a Qt-based library that maps JSON data to QVariant
+objects and vice versa.  JSON arrays are mapped to QVariantList instances,
+while JSON objects are mapped to QVariantMap.")
+    (license lgpl2.1+)))
+
 (define-public python-sip
   (package
     (name "python-sip")
@@ -517,15 +541,6 @@ contain over 620 classes.")
          %standard-phases)))
     (license (list gpl2 gpl3)))) ; choice of either license
 
-(define-public python2-pyqt-4
-  (package (inherit python-pyqt-4)
-    (name "python2-pyqt")
-    (native-inputs
-     `(("python-sip" ,python2-sip)
-       ("qt" ,qt-4)))
-    (inputs
-     `(("python" ,python-2)))))
-
 (define-public qtkeychain
   (package
     (name "qtkeychain")
@@ -540,7 +555,7 @@ contain over 620 classes.")
          (base32 "055mkd4pz6cyff4cw0784wjc1w92m8x223sxi96ph15fr3lplbg6"))))
     (build-system cmake-build-system)
     (inputs
-     `(("qt", qt)))
+     `(("qt" ,qt)))
     (arguments
      `(#:tests? #f ; No tests included
        #:phases
diff --git a/gnu/packages/rdf.scm b/gnu/packages/rdf.scm
index 13ffa2a8fe..b577e266f9 100644
--- a/gnu/packages/rdf.scm
+++ b/gnu/packages/rdf.scm
@@ -19,7 +19,7 @@
 
 (define-module (gnu packages rdf)
   #:use-module ((guix licenses)
-                #:select (non-copyleft isc gpl2 lgpl2.0+ lgpl2.1 lgpl2.1+))
+                #:select (non-copyleft isc gpl2 lgpl2.1 lgpl2.1+))
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix build-system cmake)
@@ -298,35 +298,6 @@ ideal (e.g. in LV2 implementations or embedded applications).")
      "Sord is a lightweight C library for storing RDF data in memory.")
     (license isc)))
 
-(define-public soprano
-  (package
-    (name "soprano")
-    (version "2.9.4")
-    (source (origin
-             (method url-fetch)
-             (uri (string-append "mirror://sourceforge/soprano/Soprano/"
-                                version "/"
-                                "soprano-" version ".tar.bz2"))
-             (sha256
-              (base32
-               "1rg0x7yg0a1cbnxz7kqk52580wla8jbnj4d4r3j7l7g7ajyny1k4"))
-             (patches (list (search-patch "soprano-find-clucene.patch")))))
-    (build-system cmake-build-system)
-    (native-inputs
-     `(("doxygen" ,doxygen)
-       ("pkg-config" ,pkg-config)))
-    (inputs
-     `(("clucene" ,clucene)
-       ("qt" ,qt-4)
-       ("redland" ,redland)))
-    (home-page "http://soprano.sourceforge.net/")
-    (synopsis "RDF data library for Qt")
-    (description "Soprano (formerly known as QRDF) is a library which
-provides a highly usable object-oriented C++/Qt4 framework for RDF data.  It
-uses different RDF storage solutions as backends through a simple plugin
-system.")
-    (license lgpl2.0+)))
-
 (define-public python-rdflib
   (package
     (name "python-rdflib")
diff --git a/gnu/packages/ruby.scm b/gnu/packages/ruby.scm
index fa7c2f7691..a1669d4238 100644
--- a/gnu/packages/ruby.scm
+++ b/gnu/packages/ruby.scm
@@ -1905,7 +1905,7 @@ to reproduce user environments.")
                                         "/include/libxml2" ))))
     (native-inputs
      `(("ruby-hoe" ,ruby-hoe)
-       ("ruby-rake-compiler", ruby-rake-compiler)))
+       ("ruby-rake-compiler" ,ruby-rake-compiler)))
     (inputs
      `(("zlib" ,zlib)
        ("libxml2" ,libxml2)
diff --git a/gnu/packages/scheme.scm b/gnu/packages/scheme.scm
index 352b66c59b..00b573fc0b 100644
--- a/gnu/packages/scheme.scm
+++ b/gnu/packages/scheme.scm
@@ -526,12 +526,6 @@ an isolated heap allowing multiple VMs to run simultaneously in different OS
 threads.")
     (license bsd-3)))
 
-;; FIXME: This function is temporarily in the engineering module and not
-;; exported.  It will be moved to an utility module for general use.  Once
-;; this is done, we should remove this definition.
-(define broken-tarball-fetch
-  (@@ (gnu packages engineering) broken-tarball-fetch))
-
 (define-public scmutils
   (let ()
     (define (system-suffix)
@@ -546,7 +540,7 @@ threads.")
       (version "20140302")
       (source
        (origin
-         (method broken-tarball-fetch)
+         (method url-fetch/tarbomb)
          (modules '((guix build utils)))
          (snippet
           ;; Remove binary code
diff --git a/gnu/packages/screen.scm b/gnu/packages/screen.scm
index fa5235c115..088ca559d8 100644
--- a/gnu/packages/screen.scm
+++ b/gnu/packages/screen.scm
@@ -44,7 +44,7 @@
     (native-inputs
      `(("makeinfo" ,texinfo)))
     (inputs
-     `(("ncurses", ncurses)
+     `(("ncurses" ,ncurses)
        ("perl" ,perl)))
     (arguments
      `(#:configure-flags
diff --git a/gnu/packages/ssh.scm b/gnu/packages/ssh.scm
index d4bf29cc20..081c7cbe32 100644
--- a/gnu/packages/ssh.scm
+++ b/gnu/packages/ssh.scm
@@ -1,7 +1,8 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2014, 2015, 2016 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2015 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2015, 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -44,15 +45,15 @@
 (define-public libssh
   (package
     (name "libssh")
-    (version "0.6.5")
+    (version "0.7.3")
     (source (origin
               (method url-fetch)
               (uri (string-append
-                    "https://red.libssh.org/attachments/download/121/libssh-"
+                    "https://red.libssh.org/attachments/download/195/libssh-"
                     version ".tar.xz"))
               (sha256
                (base32
-                "0b6wyx6bwbb8jpn8x4rhlrdiqwqrwrs0mxjmrnqykm9kw1ijgm8g"))))
+                "165g49i4kmm3bfsjm0n8hm21kadv79g9yjqyq09138jxanz4dvr6"))))
     (build-system cmake-build-system)
     (arguments
      '(#:configure-flags '("-DWITH_GCRYPT=ON")
@@ -60,7 +61,7 @@
        ;; TODO: Add 'CMockery' and '-DWITH_TESTING=ON' for the test suite.
        #:tests? #f))
     (inputs `(("zlib" ,zlib)
-              ("libgcrypt", libgcrypt)))
+              ("libgcrypt" ,libgcrypt)))
     (synopsis "SSH client library")
     (description
      "libssh is a C library implementing the SSHv2 and SSHv1 protocol for
@@ -70,29 +71,32 @@ remote applications.")
     (home-page "http://www.libssh.org")
     (license license:lgpl2.1+)))
 
-(define libssh-0.5                                ; kept private
+(define libssh-0.6 ; kept private for use in guile-ssh
   (package (inherit libssh)
-    (version "0.5.5")
+    (version "0.6.5")
     (source (origin
               (method url-fetch)
-              (uri (string-append "https://red.libssh.org/attachments/download/51/libssh-"
-                                  version ".tar.gz"))
+              (uri (string-append "https://red.libssh.org/attachments/"
+                                  "download/121/libssh-"
+                                  version ".tar.xz"))
               (sha256
                (base32
-                "17cfdff4hc0ijzrr15biq29fiabafz0bw621zlkbwbc1zh2hzpy0"))
-              (patches (list (search-patch "libssh-CVE-2014-0017.patch")))))))
+                "0b6wyx6bwbb8jpn8x4rhlrdiqwqrwrs0mxjmrnqykm9kw1ijgm8g"))
+              (patches (list
+                        (search-patch "libssh-0.6.5-CVE-2016-0739.patch")))))))
 
 (define-public libssh2
   (package
    (name "libssh2")
-   (version "1.4.3")
+   (version "1.7.0")
    (source (origin
             (method url-fetch)
             (uri (string-append
-                   "http://www.libssh2.org/download/libssh2-"
+                   "https://www.libssh2.org/download/libssh2-"
                    version ".tar.gz"))
-            (sha256 (base32
-                     "0vdr478dbhbdgnniqmirawjb7mrcxckn4slhhrijxnzrkmgziipa"))))
+            (sha256
+             (base32
+              "116mh112w48vv9k3f15ggp5kxw5sj4b88dzb5j69llsh7ba1ymp4"))))
    (build-system gnu-build-system)
    ;; The installed libssh2.pc file does not include paths to libgcrypt and
    ;; zlib libraries, so we need to propagate the inputs.
@@ -108,6 +112,24 @@ a server that supports the SSH-2 protocol.")
    (license license:bsd-3)
    (home-page "http://www.libssh2.org/")))
 
+;;; XXX This is a temporary package for use only by curl, to allow most users
+;;; of libssh2 to get the security update sooner while postponing the large
+;;; number of rebuilds entailed by updating curl.
+;;;
+;;; XXX This package is vulnerable to CVE-2016-7087.
+;;;
+;;; https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-0787
+(define-public libssh2-1.4
+  (package (inherit libssh2)
+    (version "1.4.3")
+    (source (origin
+             (method url-fetch)
+             (uri (string-append "https://www.libssh2.org/download/libssh2-"
+                                 version ".tar.gz"))
+             (sha256
+              (base32
+                "0vdr478dbhbdgnniqmirawjb7mrcxckn4slhhrijxnzrkmgziipa"))))))
+
 (define-public openssh
   (package
    (name "openssh")
@@ -235,7 +257,7 @@ Additionally, various channel-specific options can be negotiated.")
                      ("pkg-config" ,pkg-config)
                      ("which" ,which)))
     (inputs `(("guile" ,guile-2.0)
-              ("libssh" ,libssh)
+              ("libssh" ,libssh-0.6)
               ("libgcrypt" ,libgcrypt)))
     (synopsis "Guile bindings to libssh")
     (description
@@ -332,14 +354,15 @@ especially over Wi-Fi, cellular, and long-distance links.")
 (define-public dropbear
   (package
     (name "dropbear")
-    (version "2014.63")
+    (version "2015.71")
     (source (origin
               (method url-fetch)
               (uri (string-append
-                    "http://matt.ucc.asn.au/" name "/releases/"
+                    "https://matt.ucc.asn.au/" name "/releases/"
                     name "-" version ".tar.bz2"))
               (sha256
-               (base32 "1bjpbg2vi5f332q4bqxkidkjfxsqmnqvp4g1wyh8d99b8gg94nar"))))
+               (base32
+                "1bw3lzmisn6gs6zy9vcqbfnicl437ydskqcayklpw60fkhb18qip"))))
     (build-system gnu-build-system)
     (arguments  `(#:tests? #f)) ; There is no "make check" or anything similar
     (inputs `(("zlib" ,zlib)))
diff --git a/gnu/packages/statistics.scm b/gnu/packages/statistics.scm
index ee6fd4a20d..08e8654228 100644
--- a/gnu/packages/statistics.scm
+++ b/gnu/packages/statistics.scm
@@ -1,7 +1,8 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2015 Vicente Vera Parra <vicentemvp@gmail.com>
-;;; Copyright ©2016 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -945,14 +946,13 @@ and fast file reading.")
 (define-public python-patsy
   (package
     (name "python-patsy")
-    (version "0.4.0")
+    (version "0.4.1")
     (source (origin
               (method url-fetch)
-              (uri (string-append "https://pypi.python.org/packages/source/"
-                                  "p/patsy/patsy-" version ".zip"))
+              (uri (pypi-uri "patsy" version ".zip"))
               (sha256
                (base32
-                "1kbs996xc2haxalmhd19rr1wh5fa4gbbxf81czkf5w4kam7h7wz4"))))
+                "1m6knyq8hbqlx242y4da02j0x86j4qggs1j7q186w3jv0j0c476w"))))
     (build-system python-build-system)
     (arguments
      `(#:phases
@@ -979,20 +979,15 @@ building design matrices.")
     ;; The majority of the code is distributed under BSD-2.  The module
     ;; patsy.compat contains code derived from the Python standard library,
     ;; and is covered by the PSFL.
-    (license (list license:bsd-2 license:psfl))))
+    (license (list license:bsd-2 license:psfl))
+    (properties `((python2-variant . ,(delay python2-patsy))))))
 
 (define-public python2-patsy
-  (let ((patsy (package-with-python2 python-patsy)))
+  (let ((patsy (package-with-python2 (strip-python2-variant python-patsy))))
     (package (inherit patsy)
       (native-inputs
        `(("python2-setuptools" ,python2-setuptools)
-         ,@(package-native-inputs patsy)))
-      (propagated-inputs
-       `(("python2-numpy" ,python2-numpy)
-         ("python2-scipy" ,python2-scipy)
-         ,@(alist-delete "python-numpy"
-                         (alist-delete "python-scipy"
-                                       (package-propagated-inputs patsy))))))))
+         ,@(package-native-inputs patsy))))))
 
 (define-public python-statsmodels
   (package
diff --git a/gnu/packages/tcl.scm b/gnu/packages/tcl.scm
index 2c4c750997..1f301458a9 100644
--- a/gnu/packages/tcl.scm
+++ b/gnu/packages/tcl.scm
@@ -3,6 +3,7 @@
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
+;;; Copyright © 2016 Jan Nieuwenhuizen <janneke@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -29,6 +30,7 @@
   #:use-module (gnu packages fontutils)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages xml)
   #:use-module (gnu packages xorg)
   #:use-module (guix licenses))
 
@@ -80,8 +82,7 @@
     (home-page "http://www.tcl.tk/")
     (synopsis "The Tcl scripting language")
     (description "The Tcl (Tool Command Language) scripting language.")
-    (license (non-copyleft "http://www.tcl.tk/software/tcltk/license.html"
-                        "Tcl/Tk license"))))
+    (license tcl/tk)))
 
 
 (define-public expect
@@ -219,3 +220,73 @@ interfaces (GUIs) in the Tcl language.")
     ;; pTk/license.terms, pTk/license.html_lib, and pTk/Tix.license for
     ;; details of this license."
     (license (package-license perl))))
+
+(define-public tcllib
+  (package
+    (name "tcllib")
+    (version "1.18")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://sourceforge/" name "/"
+                                  name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "05dmrk9qsryah2n17z6z85dj9l9lfyvnsd7faw0p9bs1pp5pwrkj"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("tcl" ,tcl)))
+    (native-search-paths
+     (list (search-path-specification
+            (variable "TCLLIBPATH")
+            (separator " ")
+            (files (list (string-append "lib/tcllib" version))))))
+    (home-page "https://core.tcl.tk/tcllib/home")
+    (synopsis "Standard Tcl Library")
+    (description "Tcllib, the standard Tcl library, is a collection of common
+utility functions and modules all written in high-level Tcl.")
+    (license (package-license tcl))))
+
+(define-public tclxml
+  (package
+    (name "tclxml")
+    (version "3.2")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://sourceforge/" name "/"
+                                  name "-" version ".tar.gz"))
+              (sha256
+               (base32
+                "0ffb4aw63inig3aql33g4pk0kjk14dv238anp1scwjdjh1k6n4gl"))
+              (patches (list (search-patch "tclxml-3.2-install.patch")))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("tcl" ,tcl)
+       ("tcllib" ,tcllib)
+       ("libxml2" ,libxml2)
+       ("libxslt" ,libxslt)))
+    (native-search-paths
+     (list (search-path-specification
+            (variable "TCLLIBPATH")
+            (separator " ")
+            (files (list (string-append "lib/Tclxml" version))))))
+    (arguments
+     `(#:configure-flags
+       (list (string-append "--exec-prefix=" (assoc-ref %outputs "out"))
+             (string-append "--with-tclconfig="
+                            (assoc-ref %build-inputs "tcl") "/lib")
+             (string-append "--with-xml2-config="
+                            (assoc-ref %build-inputs "libxml2")
+                            "/bin/xml2-config")
+             (string-append "--with-xslt-config="
+                            (assoc-ref %build-inputs "libxslt")
+                            "/bin/xslt-config"))
+       #:test-target "test"))
+    (home-page "http://tclxml.sourceforge.net/")
+    (synopsis "Tcl library for XML parsing")
+    (description "TclXML provides event-based parsing of XML documents.  The
+application may register callback scripts for certain document features, and
+when the parser encounters those features while parsing the document the
+callback is evaluated.")
+    (license (non-copyleft
+              "file://LICENCE"
+              "See LICENCE in the distribution."))))
diff --git a/gnu/packages/texlive.scm b/gnu/packages/texlive.scm
index 0b2dec41f6..d8200846ac 100644
--- a/gnu/packages/texlive.scm
+++ b/gnu/packages/texlive.scm
@@ -24,6 +24,7 @@
   #:use-module (guix download)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system trivial)
+  #:use-module (guix utils)
   #:use-module (gnu packages)
   #:use-module (gnu packages bash)
   #:use-module (gnu packages compression)
@@ -45,7 +46,9 @@
   #:use-module (gnu packages xorg)
   #:use-module (gnu packages xdisorg)
   #:use-module (gnu packages zip)
-  #:autoload   (gnu packages texinfo) (texinfo))
+  #:autoload   (gnu packages texinfo) (texinfo)
+  #:use-module (ice-9 ftw)
+  #:use-module (srfi srfi-1))
 
 (define texlive-extra-src
   (origin
@@ -284,6 +287,77 @@ This package contains the complete TeX Live distribution.")
    (license (license:fsf-free "http://tug.org/texlive/copying.html"))
    (home-page "http://www.tug.org/texlive/")))
 
+
+;; texlive-texmf-minimal is a pruned, small version of the texlive tree,
+;; in particular dropping documentation and fonts.
+(define texlive-texmf-minimal
+  (package (inherit texlive-texmf)
+   (name "texlive-texmf-minimal")
+   (arguments
+    (substitute-keyword-arguments
+     (package-arguments texlive-texmf)
+     ((#:modules modules)
+      `((ice-9 ftw)
+        (srfi srfi-1)
+        ,@modules))
+     ((#:phases phases)
+      `(modify-phases ,phases
+         (add-after 'unpack 'prune
+           (lambda _
+             (define (delete subdir exclude)
+               "Delete all files and directories in SUBDIR except for those
+given in the list EXCLUDE."
+               (with-directory-excursion subdir
+                 (for-each delete-file-recursively
+                           (lset-difference equal?
+                                            (scandir ".")
+                                            (append '("." "..")
+                                                    exclude)))))
+             (with-directory-excursion "texmf-dist"
+               (for-each delete-file-recursively
+                         '("doc" "source" "tex4ht"))
+               ;; Delete all subdirectories of "fonts", except for "tfm" and
+               ;; any directories named "cm".
+               (delete "fonts" '("afm" "map" "pk" "source" "tfm" "type1"))
+               (delete "fonts/afm" '("public"))
+               (delete "fonts/afm/public" '("amsfonts"))
+               (delete "fonts/afm/public/amsfonts" '("cm"))
+               (delete "fonts/map" '("dvips"))
+               (delete "fonts/map/dvips" '("cm"))
+               (delete "fonts/source" '("public"))
+               (delete "fonts/source/public" '("cm"))
+               (delete "fonts/tfm" '("public"))
+               (delete "fonts/type1" '("public"))
+               (delete "fonts/type1/public" '("amsfonts"))
+               (delete "fonts/type1/public/amsfonts" '("cm")))
+             #t))))))
+   (description
+    "TeX Live provides a comprehensive TeX document production system.
+It includes all the major TeX-related programs, macro packages, and fonts
+that are free software, including support for many languages around the
+world.
+
+This package contains a small subset of the texmf-dist data.")))
+
+
+;; texlive-minimal is the same as texlive, but using texlive-texmf-minimal
+;; instead of the full texlive-texmf. It can be used, for instance, as a
+;; native input to packages that need texlive to build their documentation.
+(define-public texlive-minimal
+  (package (inherit texlive)
+   (name "texlive-minimal")
+   (inputs
+    `(("texlive-texmf" ,texlive-texmf-minimal)
+      ,@(alist-delete "texlive-texmf" (package-inputs texlive))))
+   (description
+    "TeX Live provides a comprehensive TeX document production system.
+It includes all the major TeX-related programs, macro packages, and fonts
+that are free software, including support for many languages around the
+world.
+
+This package contains a small working part of the TeX Live distribution.")))
+
+
 (define-public rubber
   (package
     (name "rubber")
diff --git a/gnu/packages/textutils.scm b/gnu/packages/textutils.scm
index f2c60ddadf..6f3782fa7b 100644
--- a/gnu/packages/textutils.scm
+++ b/gnu/packages/textutils.scm
@@ -1,7 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer <taylanbayirli@gmail.com>
 ;;; Copyright © 2015, 2016 Ricardo Wurmus <rekado@elephly.net>
-;;; Copyright © 2015 Ben Woodcroft <donttrustben@gmail.com>
+;;; Copyright © 2015, 2016 Ben Woodcroft <donttrustben@gmail.com>
 ;;; Copyright © 2015 Roel Janssen <roel@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -152,11 +152,10 @@ the Hannon Lab.")
     (license license:agpl3+)))
 
 (define-public cityhash
-  (let ((commit "8af9b8c")
-        (revision "1"))
+  (let ((commit "8af9b8c"))
     (package
       (name "cityhash")
-      (version (string-append "1.1." revision "." commit))
+      (version (string-append "1.1-2." commit))
       (source (origin
                 (method git-fetch)
                 (uri (git-reference
@@ -166,13 +165,25 @@ the Hannon Lab.")
                 (sha256
                  (base32
                   "0n6skf5dv8yfl1ckax8dqhvsbslkwc9158zf2ims0xqdvzsahbi6"))))
-    (build-system gnu-build-system)
-    (home-page "https://github.com/google/cityhash")
-    (synopsis "C++ hash functions for strings")
-    (description
-     "CityHash provides hash functions for strings.  The functions mix the
+      (build-system gnu-build-system)
+      (arguments
+       '(#:make-flags (list "CXXFLAGS=-g -O3")
+         #:phases
+         (modify-phases %standard-phases
+           ;; citycrc is not installed by default but is used by some
+           ;; programs.
+           (add-after 'install 'install-citycrc
+             (lambda* (#:key outputs #:allow-other-keys)
+               (let* ((out (assoc-ref outputs "out"))
+                      (include (string-append out "/include")))
+                 (install-file "src/citycrc.h" include))
+               #t)))))
+      (home-page "https://github.com/google/cityhash")
+      (synopsis "C++ hash functions for strings")
+      (description
+       "CityHash provides hash functions for strings.  The functions mix the
 input bits thoroughly but are not suitable for cryptography.")
-    (license license:expat))))
+      (license license:expat))))
 
 (define-public libconfig
   (package
diff --git a/gnu/packages/tls.scm b/gnu/packages/tls.scm
index 703cb299e1..4f2c7af3de 100644
--- a/gnu/packages/tls.scm
+++ b/gnu/packages/tls.scm
@@ -73,7 +73,7 @@ specifications.")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "http://p11-glue.freedesktop.org/releases/p11-kit-"
+      (uri (string-append "https://p11-glue.freedesktop.org/releases/p11-kit-"
                           version ".tar.gz"))
       (sha256
        (base32
@@ -318,57 +318,107 @@ security, and applying best practice development processes.")
                      "file://COPYING"
                      "See COPYING in the distribution.")))))
 
-(define-public acme
+(define-public python-acme
   (package
-    (name "acme")
-    (version "0.2.0")
+    (name "python-acme")
+    (version "0.4.0")
     (source (origin
       (method url-fetch)
       (uri (pypi-uri "acme" version))
       (sha256
         (base32
-         "1xcbywzrwrj2cmqhaj4k6b11wfkbm3i7za2k9j1sd74rs1zh5abl"))))
+         "173j2zkslh43fzf3wkl1jdzfjry361m0mhlc3jpwp7hk7lrclzjg"))))
     (build-system python-build-system)
     (arguments
-     `(#:python ,python-2))
-    ;; TODO: Add optional inputs for testing and building documentation.
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-before 'install 'disable-egg-compression
+           (lambda _
+             ;; Do not compress the egg.
+             ;; See <http://bugs.gnu.org/20765>.
+             (let ((port (open-file "setup.cfg" "a")))
+               (display "\n[easy_install]\nzip_ok = 0\n"
+                        port)
+               (close-port port)
+               #t)))
+         (add-after 'install 'docs
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (man (string-append out "/share/man/man1"))
+                    (info (string-append out "/info")))
+               (and (zero? (system* "make" "-C" "docs" "man" "info"))
+                    (install-file "docs/_build/texinfo/acme-python.info" info)
+                    (install-file "docs/_build/man/acme-python.1" man)
+                    #t)))))))
+    ;; TODO: Add optional inputs for testing.
     (native-inputs
-     `(("python2-mock" ,python2-mock)
-       ("python2-setuptools" ,python2-setuptools)))
+     `(("python-mock" ,python-mock)
+       ;; For documentation
+       ("python-sphinx" ,python-sphinx)
+       ("python-sphinxcontrib-programoutput" ,python-sphinxcontrib-programoutput)
+       ("python-sphinx-rtd-theme" ,python-sphinx-rtd-theme)
+       ("python-setuptools" ,python-setuptools)
+       ("texinfo" ,texinfo)))
     (propagated-inputs
-     `(("python2-ndg-httpsclient" ,python2-ndg-httpsclient)
-       ("python2-werkzeug" ,python2-werkzeug)
-       ("python2-six" ,python2-six)
-       ("python2-requests" ,python2-requests)
-       ("python2-pytz" ,python2-pytz)
-       ("python2-pyrfc3339" ,python2-pyrfc3339)
-       ("python2-pyasn1" ,python2-pyasn1)
-       ("python2-cryptography" ,python2-cryptography)
-       ("python2-pyopenssl" ,python2-pyopenssl)))
+     `(("python-ndg-httpsclient" ,python-ndg-httpsclient)
+       ("python-werkzeug" ,python-werkzeug)
+       ("python-six" ,python-six)
+       ("python-requests" ,python-requests)
+       ("python-pytz" ,python-pytz)
+       ("python-pyrfc3339" ,python-pyrfc3339)
+       ("python-pyasn1" ,python-pyasn1)
+       ("python-cryptography" ,python-cryptography)
+       ("python-pyopenssl" ,python-pyopenssl)))
     (home-page "https://github.com/letsencrypt/letsencrypt")
     (synopsis "ACME protocol implementation in Python")
     (description "ACME protocol implementation in Python")
     (license license:asl2.0)))
 
+(define-public python2-acme
+  (package-with-python2 python-acme))
+
 (define-public letsencrypt
   (package
     (name "letsencrypt")
-    (version "0.2.0")
+    (version "0.4.0")
     (source (origin
               (method url-fetch)
               (uri (pypi-uri "letsencrypt" version))
               (sha256
                (base32
-                "0q57ylx00b6kl9zvawgag5yl03vlv1cjhp18xm96682pdibbgjci"))))
+                "1wwq8yvfdybf4d0gv4yfddkrg865s7rhng5xg563kks4wza1a2wp"))))
     (build-system python-build-system)
     (arguments
-     `(#:python ,python-2))
-    ;; TODO: Add optional inputs for testing building documentation.
+     `(#:python ,python-2
+       #:phases
+       (modify-phases %standard-phases
+         (add-after 'install 'docs
+           (lambda* (#:key outputs #:allow-other-keys)
+             (let* ((out (assoc-ref outputs "out"))
+                    (man1 (string-append out "/share/man/man1"))
+                    (man7 (string-append out "/share/man/man7"))
+                    (info (string-append out "/info")))
+               (substitute* "docs/man/letsencrypt.rst"
+                 (("letsencrypt --help all")
+                  (string-append out "/bin/letsencrypt" " --help all")))
+               (and
+                 (zero? (system* "make" "-C" "docs" "man" "info"))
+                 (install-file "docs/_build/texinfo/LetsEncrypt.info" info)
+                 (install-file "docs/_build/man/letsencrypt.1" man1)
+                 (install-file "docs/_build/man/letsencrypt.7" man7)
+                 #t)))))))
+    ;; TODO: Add optional inputs for testing.
     (native-inputs
      `(("python2-nose" ,python2-nose)
-       ("python2-mock" ,python2-mock)))
+       ("python2-mock" ,python2-mock)
+       ;; For documentation
+       ("python2-sphinx" ,python2-sphinx)
+       ("python2-sphinx-rtd-theme" ,python2-sphinx-rtd-theme)
+       ("python2-sphinx-repoze-autointerface" ,python2-sphinx-repoze-autointerface)
+       ("python2-sphinxcontrib-programoutput" ,python2-sphinxcontrib-programoutput)
+       ("texinfo" ,texinfo)))
     (propagated-inputs
-     `(("acme" ,acme)
+     `(("python2-acme" ,python2-acme)
        ("python2-zope-interface" ,python2-zope-interface)
        ("python2-pythondialog" ,python2-pythondialog)
        ("python2-pyrfc3339" ,python2-pyrfc3339)
diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scm
index e0626cb3ac..0712f9f392 100644
--- a/gnu/packages/version-control.scm
+++ b/gnu/packages/version-control.scm
@@ -30,6 +30,7 @@
                 #:select (asl2.0 bsd-2
                           gpl1+ gpl2 gpl2+ gpl3+ lgpl2.1
                           x11-style))
+  #:use-module (guix utils)
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix git-download)
@@ -75,15 +76,16 @@
 (define-public bazaar
   (package
     (name "bazaar")
-    (version "2.6.0")
+    (version "2.7.0")
     (source
      (origin
       (method url-fetch)
-      (uri (string-append "https://launchpad.net/bzr/2.6/" version
+      (uri (string-append "https://launchpad.net/bzr/"
+                          (version-major+minor version) "/" version
                           "/+download/bzr-" version ".tar.gz"))
       (sha256
        (base32
-        "1c6sj77h5f97qimjc14kr532kgc0jk3wq778xrkqi0pbh9qpk509"))))
+        "1cysix5k3wa6y7jjck3ckq3abls4gvz570s0v0hxv805nwki4i8d"))))
     (build-system python-build-system)
     (inputs
      ;; Note: 'tools/packaging/lp-upload-release' and 'tools/weavemerge.sh'
diff --git a/gnu/packages/video.scm b/gnu/packages/video.scm
index bc155fba18..7d6c363da8 100644
--- a/gnu/packages/video.scm
+++ b/gnu/packages/video.scm
@@ -187,14 +187,14 @@ television and DVD.  It is also known as AC-3.")
 (define-public libx264
   (package
     (name "libx264")
-    (version "20150706-2245")
+    (version "20160220-2245")
     (source (origin
               (method url-fetch)
-              (uri (string-append "ftp://ftp.videolan.org/pub/x264/snapshots/"
+              (uri (string-append "http://download.videolan.org/pub/x264/snapshots/"
                                   "x264-snapshot-" version ".tar.bz2"))
               (sha256
                (base32
-                "0v04xq25q66gsk78i4kryy7503ki87jxbhln2c0qpvyy0d47p466"))))
+                "12zyzbiihfhamf7yi4qqaj6k0nisnrydvfr36kxadvmsm7dg4sj3"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
@@ -327,7 +327,7 @@ SMPTE 314M.")
      (origin
        (method url-fetch)
        (uri (string-append
-             "http://www.freedesktop.org/software/vaapi/releases/libva/libva-"
+             "https://www.freedesktop.org/software/vaapi/releases/libva/libva-"
              version".tar.bz2"))
        (sha256
         (base32 "0bjfb5s8dk3lql843l91ffxzlq47isqks5sj19cxh7j3nhzw58kz"))))
@@ -406,7 +406,7 @@ standards (MPEG-2, MPEG-4 ASP/H.263, MPEG-4 AVC/H.264, and VC-1/VMW3).")
        ("speex" ,speex)
        ("twolame" ,twolame)
        ("xvid" ,xvid)
-       ("zlib", zlib)))
+       ("zlib" ,zlib)))
     (native-inputs
      `(("bc" ,bc)
        ("perl" ,perl)
@@ -608,7 +608,7 @@ treaming protocols.")
     (source (origin
              (method url-fetch)
              (uri (string-append
-                   "http://www.mplayerhq.hu/MPlayer/releases/MPlayer-"
+                   "https://www.mplayerhq.hu/MPlayer/releases/MPlayer-"
                    version ".tar.xz"))
              (sha256
               (base32
@@ -620,23 +620,28 @@ treaming protocols.")
     (inputs
      `(("alsa-lib" ,alsa-lib)
        ("cdparanoia" ,cdparanoia)
+       ("ffmpeg" ,ffmpeg)
        ("fontconfig" ,fontconfig)
-       ("ffmpeg", ffmpeg)
        ("freetype" ,freetype)
-       ("lame" ,lame)
-       ("libdvdcss", libdvdcss)
-       ("libdvdnav", libdvdnav)
-       ("libmpg123" ,mpg123)                      ; audio codec for MP3
 ;;        ("giflib" ,giflib) ; uses QuantizeBuffer, requires version >= 5
+       ("lame" ,lame)
+       ("libass" ,libass)
+       ("libdvdcss" ,libdvdcss)
+       ("libdvdnav" ,libdvdnav)
        ("libjpeg" ,libjpeg)
+       ("libmpeg2" ,libmpeg2)
+       ("libmpg123" ,mpg123)                      ; audio codec for MP3
        ("libpng" ,libpng)
        ("libtheora" ,libtheora)
+       ("libvdpau" ,libvdpau)
        ("libvorbis" ,libvorbis)
        ("libx11" ,libx11)
-       ("libxxf86dga" ,libxxf86dga)
+       ("libx264" ,libx264)
        ("libxinerama" ,libxinerama)
        ("libxv" ,libxv)
+       ("libxxf86dga" ,libxxf86dga)
        ("mesa" ,mesa)
+       ("opus" ,opus)
        ("perl" ,perl)
        ("pulseaudio" ,pulseaudio)
        ("python" ,python-wrapper)
@@ -647,8 +652,8 @@ treaming protocols.")
     (arguments
      `(#:tests? #f ; no test target
        #:phases
-         (alist-replace
-          'configure
+       (modify-phases %standard-phases
+        (replace 'configure
           ;; configure does not work followed by "SHELL=..." and
           ;; "CONFIG_SHELL=..."; set environment variables instead
           (lambda* (#:key inputs outputs #:allow-other-keys)
@@ -662,7 +667,7 @@ treaming protocols.")
                       "./configure"
                       (string-append "--extra-cflags=-I"
                                      libx11 "/include") ; to detect libx11
-		       "--disable-ffmpeg_a" ; disables bundled ffmpeg
+                      "--disable-ffmpeg_a" ; disables bundled ffmpeg
                       (string-append "--prefix=" out)
                       ;; Enable runtime cpu detection where supported,
                       ;; and choose a suitable target.
@@ -681,9 +686,8 @@ treaming protocols.")
                                     (or (%current-target-system)
                                         (nix-system->gnu-triplet
                                          (%current-system)))))))
-                      "--disable-iwmmxt"))))
-          %standard-phases)))
-    (home-page "http://www.mplayerhq.hu/design7/news.html")
+                      "--disable-iwmmxt"))))))))
+    (home-page "https://www.mplayerhq.hu/design7/news.html")
     (synopsis "Audio and video player")
     (description "MPlayer is a movie player.  It plays most MPEG/VOB, AVI,
 Ogg/OGM, VIVO, ASF/WMA/WMV, QT/MOV/MP4, RealMedia, Matroska, NUT,
@@ -770,7 +774,7 @@ projects while introducing many more.")
 (define-public libvpx
   (package
     (name "libvpx")
-    (version "1.4.0")
+    (version "1.5.0")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://storage.googleapis.com/"
@@ -778,23 +782,23 @@ projects while introducing many more.")
                                   name "-" version ".tar.bz2"))
               (sha256
                (base32
-                "1r0ql5kgy0c8mh5w7iiqvsd7w5njl9f9cclc7m52ln8assrdk0pm"))))
+                "15v7qw0ydyxn08ksb6lxn1l51pxgpwgshdwd3275yrr5hs86fv9h"))))
     (build-system gnu-build-system)
     (arguments
-     `(#:phases (alist-replace
-                 'configure
-                 (lambda* (#:key outputs #:allow-other-keys)
-                   (setenv "CONFIG_SHELL" (which "bash"))
-                   (let ((out (assoc-ref outputs "out")))
-                     (setenv "LDFLAGS"
-                             (string-append "-Wl,-rpath=" out "/lib"))
-                     (zero? (system* "./configure"
-                                     "--enable-shared"
-                                     "--as=yasm"
-                                     ;; Limit size to avoid CVE-2015-1258
-                                     "--size-limit=16384x16384"
-                                     (string-append "--prefix=" out)))))
-                 %standard-phases)
+     `(#:phases
+       (modify-phases %standard-phases
+         (replace 'configure
+           (lambda* (#:key outputs #:allow-other-keys)
+             (setenv "CONFIG_SHELL" (which "bash"))
+             (let ((out (assoc-ref outputs "out")))
+               (setenv "LDFLAGS"
+                       (string-append "-Wl,-rpath=" out "/lib"))
+               (zero? (system* "./configure"
+                               "--enable-shared"
+                               "--as=yasm"
+                               ;; Limit size to avoid CVE-2015-1258
+                               "--size-limit=16384x16384"
+                               (string-append "--prefix=" out)))))))
        #:tests? #f)) ; no check target
     (native-inputs
      `(("perl" ,perl)
@@ -807,7 +811,7 @@ projects while introducing many more.")
 (define-public youtube-dl
   (package
     (name "youtube-dl")
-    (version "2016.02.01")
+    (version "2016.02.22")
     (source (origin
               (method url-fetch)
               (uri (string-append "http://youtube-dl.org/downloads/"
@@ -815,7 +819,7 @@ projects while introducing many more.")
                                   version ".tar.gz"))
               (sha256
                (base32
-                "04r68acrhx7wapmxph6lcf8hh0pnp76h9p85gcxpidc9m7ypzjfa"))))
+                "02k3kmcrhd04j5y4iivbdms9kvkjw27cqbwd3hf4agd2jjpigkql"))))
     (build-system python-build-system)
     (native-inputs `(("python-setuptools" ,python-setuptools)))
     (home-page "http://youtube-dl.org")
@@ -1157,7 +1161,7 @@ format changes.")
 (define-public xvid
   (package
     (name "xvid")
-    (version "1.3.3")
+    (version "1.3.4")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -1165,18 +1169,18 @@ format changes.")
                     version ".tar.bz2"))
               (sha256
                (base32
-                "0m5g75qvapr7xpywg6a83v5x19kw1nm9l2q48lg7jvvpba0bmqdh"))))
+                "1xwbmp9wqshc0ckm970zdpi0yvgqxlqg0s8bkz98mnr8p2067bsz"))))
     (build-system gnu-build-system)
     (native-inputs `(("yasm" ,yasm)))
     (arguments
      '(#:phases
-       (alist-cons-before
-        'configure 'pre-configure
-        (lambda _
-          (chdir "build/generic")
-          (substitute* "configure"
-            (("#! /bin/sh") (string-append "#!" (which "sh")))))
-        %standard-phases)
+       (modify-phases %standard-phases
+         (add-before
+          'configure 'pre-configure
+          (lambda _
+            (chdir "build/generic")
+            (substitute* "configure"
+              (("#! /bin/sh") (string-append "#!" (which "sh")))))))
        ;; No 'check' target.
        #:tests? #f))
     (home-page "https://www.xvid.com/")
@@ -1300,7 +1304,7 @@ be used for realtime video capture via Linux-specific APIs.")
 (define-public obs
   (package
     (name "obs")
-    (version "0.13.0")
+    (version "0.13.1")
     (source (origin
               (method url-fetch)
               (uri (string-append "https://github.com/jp9000/obs-studio"
@@ -1308,7 +1312,7 @@ be used for realtime video capture via Linux-specific APIs.")
               (file-name (string-append name "-" version ".tar.gz"))
               (sha256
                (base32
-                "1rk5yfcqwjj4a8bj35fsfzk5qlsf5ylsy0z7kdrpl3fhnmla2izz"))))
+                "1vsn4r3wzfdwjrn69kgx3c5wfx17i72nxdv298pq772fp4j2iy2r"))))
     (build-system cmake-build-system)
     (arguments '(#:tests? #f)) ; no tests
     (native-inputs
diff --git a/gnu/packages/vim.scm b/gnu/packages/vim.scm
index e117fc4dff..241896323c 100644
--- a/gnu/packages/vim.scm
+++ b/gnu/packages/vim.scm
@@ -53,10 +53,10 @@
              (("/bin/sh") (which "sh"))))
           %standard-phases)))
     (inputs
-     `(("gawk", gawk)
-       ("inetutils", inetutils)
-       ("ncurses", ncurses)
-       ("perl", perl)
+     `(("gawk" ,gawk)
+       ("inetutils" ,inetutils)
+       ("ncurses" ,ncurses)
+       ("perl" ,perl)
        ("tcsh" ,tcsh))) ; For runtime/tools/vim32
     (home-page "http://www.vim.org/")
     (synopsis "Text editor based on vi")
diff --git a/gnu/packages/wine.scm b/gnu/packages/wine.scm
index 4c7e7a4596..54cb65503c 100644
--- a/gnu/packages/wine.scm
+++ b/gnu/packages/wine.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015 Sou Bunnbu <iyzsong@gmail.com>
+;;; Copyright © 2016 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -20,6 +21,7 @@
   #:use-module ((guix licenses) #:prefix license:)
   #:use-module (guix packages)
   #:use-module (guix download)
+  #:use-module (guix utils)
   #:use-module (guix build-system gnu)
   #:use-module (gnu packages)
   #:use-module (gnu packages audio)
@@ -50,18 +52,15 @@
 (define-public wine
   (package
     (name "wine")
-    (version "1.7.52")
+    (version "1.9.4")
     (source (origin
               (method url-fetch)
-              (uri (string-append "mirror://sourceforge/wine/"
-                                  name "-" version ".tar.bz2"))
+              (uri (string-append "https://dl.winehq.org/wine/source/"
+                                  (version-major+minor version)
+                                  "/wine-" version ".tar.bz2"))
               (sha256
                (base32
-                "0jsm1p7zwhfb5fpp0xd39vnx9m98kqgfng1q9kdj70rm1hmb6wq7"))
-              (modules '((guix build utils)))
-              (snippet
-               '(substitute* "Make.vars.in"
-                  (("/bin/sh") "@SHELL@")))))
+                "1f5v1gns0xs512a6ym785cn29j8dxdbnxnvkg8v0p1w0p6vfmhbm"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)
                      ("gettext" ,gnu-gettext)
@@ -114,6 +113,9 @@
        #:configure-flags
        (list (string-append "LDFLAGS=-Wl,-rpath=" %output "/lib"))
 
+       #:make-flags
+       (list "SHELL=bash")
+
        #:phases
        (alist-cons-after
         'configure 'patch-dlopen-paths
diff --git a/gnu/packages/xdisorg.scm b/gnu/packages/xdisorg.scm
index 3ec3e69645..5bc2faba1c 100644
--- a/gnu/packages/xdisorg.scm
+++ b/gnu/packages/xdisorg.scm
@@ -211,7 +211,7 @@ rasterisation.")
       (origin
         (method url-fetch)
         (uri (string-append
-               "http://dri.freedesktop.org/libdrm/libdrm-"
+               "https://dri.freedesktop.org/libdrm/libdrm-"
                version
                ".tar.bz2"))
         (sha256
@@ -268,7 +268,7 @@ tracking.")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "http://www.freedesktop.org/software/" name
+       (uri (string-append "https://www.freedesktop.org/software/" name
                            "/releases/" name "-" version ".tar.gz"))
        (sha256
         (base32
@@ -542,7 +542,7 @@ compact configuration syntax.")
     (version "9.21")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://dist.schmorp.de/rxvt-unicode/"
+              (uri (string-append "http://dist.schmorp.de/rxvt-unicode/Attic/"
                                   name "-" version ".tar.bz2"))
               (sha256
                (base32
@@ -626,19 +626,21 @@ Escape key when Left Control is pressed and released on its own.")
     (native-inputs
      `(("pkg-config" ,pkg-config)))
     (inputs
-     `(("glib" ,glib)
-       ("gtk+" ,gtk+)
+     `(("gtk+" ,gtk+)
        ("libgudev" ,libgudev)
        ("eudev" ,eudev)
        ("libxml2" ,libxml2)))
+    (propagated-inputs
+     ;; libwacom includes header files that include GLib, and libinput uses
+     ;; those header files.
+     `(("glib" ,glib)))
     (home-page "http://linuxwacom.sourceforge.net/")
     (synopsis "Helper library for Wacom tablet settings")
     (description
-     "Libwacom is a library to help implement Wacom tablet settings.  It
-is intended to be used by client-programs that need model identification.  It
-is already being used by the gnome-settings-daemon and the GNOME 3.4 Control
-Center Wacom tablet applet.  In the future, the xf86-input-wacom driver may
-use it as well.")
+     "Libwacom is a library to help implement Wacom tablet settings.  It is
+intended to be used by client-programs that need model identification.  It is
+already being used by the gnome-settings-daemon and the GNOME Control Center
+Wacom tablet applet.")
     (license license:x11)))
 
 (define-public xf86-input-wacom
@@ -680,7 +682,7 @@ the X.Org X Server version 1.7 and later (X11R7.5 or later).")
 (define-public redshift
   (package
     (name "redshift")
-    (version "1.10")
+    (version "1.11")
     (source
      (origin
        (method url-fetch)
@@ -690,7 +692,7 @@ the X.Org X Server version 1.7 and later (X11R7.5 or later).")
                        "/redshift-" version ".tar.xz"))
        (sha256
         (base32
-         "19pfk9il5x2g2ivqix4a555psz8mj3m0cvjwnjpjvx0llh5fghjv"))))
+         "0ngkwj7rg8nfk806w0sg443w6wjr91xdc0zisqfm5h2i77wm1qqh"))))
     (build-system gnu-build-system)
     (native-inputs
      `(("pkg-config" ,pkg-config)
@@ -699,7 +701,7 @@ the X.Org X Server version 1.7 and later (X11R7.5 or later).")
      `(("libdrm" ,libdrm)
        ("libx11" ,libx11)
        ("libxcb" ,libxcb)
-       ("libxxf86vm", libxxf86vm)
+       ("libxxf86vm" ,libxxf86vm)
        ("glib" ,glib)))                           ;for Geoclue2 support
     (home-page "https://github.com/jonls/redshift")
     (synopsis "Adjust the color temperature of your screen")
diff --git a/gnu/packages/xfce.scm b/gnu/packages/xfce.scm
index e213fb6067..2aef842d5a 100644
--- a/gnu/packages/xfce.scm
+++ b/gnu/packages/xfce.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014, 2015 Sou Bunnbu <iyzsong@gmail.com>
 ;;; Copyright © 2014, 2015 Mark H Weaver <mhw@netris.org>
+;;; Copyright © 2016 Andreas Enge <andreas@enge.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -281,7 +282,7 @@ management D-Bus specification.")
      `(("libxfce4util" ,libxfce4util))) ; required by libxfce4panel-1.0.pc
     (inputs
      `(("exo" ,exo)
-       ("garcon", garcon)
+       ("garcon" ,garcon)
        ("libwnck" ,libwnck-1)
        ("libxfce4ui" ,libxfce4ui)))
     (native-search-paths
@@ -387,6 +388,44 @@ to an auto mixer tool like pavucontrol.  It can optionally handle multimedia
 keys for controlling the audio volume.")
     (license gpl2+)))
 
+(define-public xfce4-xkb-plugin
+  (package
+    (name "xfce4-xkb-plugin")
+    (version "0.7.1")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "http://archive.xfce.org/src/panel-plugins/"
+                                  name "/" (version-major+minor version) "/"
+                                  name "-" version ".tar.bz2"))
+              (sha256
+               (base32
+                "10g65j5ia389ahhn3b9hr52ghpp0817fk0m60rfrv4wrzqrjxzk1"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     `(("intltool" ,intltool)
+       ("pkg-config" ,pkg-config)))
+    (inputs
+     `(("garcon" ,garcon)
+       ("librsvg" ,librsvg)
+       ("libwnck" ,libwnck-1)
+       ("libx11" ,libx11)
+       ("libxfce4ui" ,libxfce4ui)
+       ("libxklavier" ,libxklavier)
+       ("xfce4-panel" ,xfce4-panel)))
+    (home-page "http://git.xfce.org/panel-plugins/xfce4-xkb-plugin/")
+    (synopsis "XKB layout switching panel plug-in for Xfce")
+    (description
+     "Xfce XKB plugin makes it possible to set up and use multiple
+keyboard layouts.
+
+One can choose the keyboard model, what key combination to
+use to switch between the layouts, the actual keyboard layouts,
+the way in which the current layout is being displayed (country
+flag image or text) and the layout policy, which is whether to
+store the layout globally (for all windows), per application or
+per window.")
+    (license bsd-2)))
+
 (define-public xfce4-appfinder
   (package
     (name "xfce4-appfinder")
@@ -480,7 +519,7 @@ allows you to shutdown the computer from Xfce.")
      `(("exo" ,exo)
        ("garcon" ,garcon)
        ("libnotify" ,libnotify)
-       ("libxcursor", libxcursor)
+       ("libxcursor" ,libxcursor)
        ("libxi" ,libxi)
        ("libxklavier" ,libxklavier)
        ("libxrandr" ,libxrandr)
@@ -695,7 +734,8 @@ on your desktop.")
        ;; Panel plugins.
        ("xfce4-battery-plugin"    ,xfce4-battery-plugin)
        ("xfce4-clipman-plugin"    ,xfce4-clipman-plugin)
-       ("xfce4-pulseaudio-plugin" ,xfce4-pulseaudio-plugin)))
+       ("xfce4-pulseaudio-plugin" ,xfce4-pulseaudio-plugin)
+       ("xfce4-xkb-plugin" ,xfce4-xkb-plugin)))
     (home-page "http://www.xfce.org/")
     (synopsis "Desktop environment (meta-package)")
     (description
diff --git a/gnu/packages/xnee.scm b/gnu/packages/xnee.scm
index 4e9135dd5b..84dd85b2e7 100644
--- a/gnu/packages/xnee.scm
+++ b/gnu/packages/xnee.scm
@@ -39,7 +39,7 @@
                "04n2lac0vgpv8zsn7nmb50hf3qb56pmj90dmwnivg09gyrf1x92j"))))
     (build-system gnu-build-system)
     (inputs
-     `(("gtk+", gtk+-2)
+     `(("gtk+" ,gtk+-2)
        ("inputproto" ,inputproto)
        ("libx11" ,libx11)
        ("libxext" ,libxext)
diff --git a/gnu/packages/xorg.scm b/gnu/packages/xorg.scm
index 82a5d994d2..f69661d088 100644
--- a/gnu/packages/xorg.scm
+++ b/gnu/packages/xorg.scm
@@ -132,7 +132,7 @@ autotools system.")
 (define-public bdftopcf
   (package
     (name "bdftopcf")
-    (version "1.0.4")
+    (version "1.0.5")
     (source
       (origin
         (method url-fetch)
@@ -142,7 +142,7 @@ autotools system.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1617zmgnx50n7vxlqyj84fl7vnk813jjqmi6jpigyz1xp9br1xga"))))
+            "09i03sk878cmx2i40lkpsysn7zqcvlczb30j7x3lryb11jz4gx1q"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxfont" ,libxfont)))
@@ -348,7 +348,7 @@ provided.")
     (build-system gnu-build-system)
     (inputs
       `(("bdftopcf" ,bdftopcf)
-        ("font-util", font-util)
+        ("font-util" ,font-util)
         ("mkfontdir" ,mkfontdir)))
     (native-inputs
       `(("pkg-config" ,pkg-config)))
@@ -380,7 +380,7 @@ provided.")
     (build-system gnu-build-system)
     (inputs
       `(("bdftopcf" ,bdftopcf)
-        ("font-util", font-util)
+        ("font-util" ,font-util)
         ("mkfontdir" ,mkfontdir)))
     (native-inputs
       `(("pkg-config" ,pkg-config)))
@@ -817,7 +817,7 @@ For example: '6x10', '9x15bold', etc.")
 (define-public font-util
   (package
     (name "font-util")
-    (version "1.3.0")
+    (version "1.3.1")
     (source
       (origin
         (method url-fetch)
@@ -827,7 +827,7 @@ For example: '6x10', '9x15bold', etc.")
                ".tar.bz2"))
         (sha256
           (base32
-            "15cijajwhjzpy3ydc817zz8x5z4gbkyv3fps687jbq544mbfbafz"))))
+            "08drjb6cf84pf5ysghjpb4i7xkd2p86k3wl2a0jxs1jif6qbszma"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)))
     (home-page "http://www.x.org/wiki/")
@@ -939,7 +939,7 @@ rendering commands to the X server.")
 (define-public iceauth
   (package
     (name "iceauth")
-    (version "1.0.6")
+    (version "1.0.7")
     (source
       (origin
         (method url-fetch)
@@ -949,7 +949,7 @@ rendering commands to the X server.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1x72y99dxf2fxnlyf0yrf9yzd8xzimxshy6l8mprwhrv6lvhi6dx"))))
+            "02izdyzhwpgiyjd8brzilwvwnfr72ncjb6mzz3y1icwrxqnsy5hj"))))
     (build-system gnu-build-system)
     (inputs
       `(("libice" ,libice)))
@@ -992,7 +992,7 @@ devices management such as graphic tablets.")
 (define-public kbproto
   (package
     (name "kbproto")
-    (version "1.0.6")
+    (version "1.0.7")
     (source
       (origin
         (method url-fetch)
@@ -1002,7 +1002,7 @@ devices management such as graphic tablets.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0yal11hhpiisy3w8wmacsdzzzcnc3xwnswxz8k7zri40xc5aqz03"))))
+            "0mxqj1pzhjpz9495vrjnpi10kv2n1s4vs7di0sh3yvipfq5j30pq"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)))
     (home-page "http://www.x.org/wiki/")
@@ -1049,7 +1049,7 @@ of new capabilities and controls for text keyboards.")
 (define-public libxshmfence
   (package
     (name "libxshmfence")
-    (version "1.1")
+    (version "1.2")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -1057,7 +1057,7 @@ of new capabilities and controls for text keyboards.")
                     name "-" version ".tar.bz2"))
               (sha256
                (base32
-                "1gnfb1z8sbbdc3xpz1zmm94lv7yvfh4kvip9s5pj37ya4llxphnv"))))
+                "032b0nlkdrpbimdld4gqvhqx53rzn8fawvf1ybhzn7lcswgjs6yj"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)))
     (inputs `(("xproto" ,xproto)))
@@ -1074,7 +1074,7 @@ synchronization between the X server and direct-rendering clients.")
 (define-public libfontenc
   (package
     (name "libfontenc")
-    (version "1.1.2")
+    (version "1.1.3")
     (source
       (origin
         (method url-fetch)
@@ -1084,7 +1084,7 @@ synchronization between the X server and direct-rendering clients.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0qign0ivqk166l9yfd51gw9lbhgs718bcrmvc40yicjr6gnyz959"))))
+            "08gxmrhgw97mv0pvkfmd46zzxrn6zdw4g27073zl55gwwqq8jn3h"))))
     (build-system gnu-build-system)
     (inputs
       `(("zlib" ,zlib)
@@ -1100,7 +1100,7 @@ synchronization between the X server and direct-rendering clients.")
 (define-public libfs
   (package
     (name "libfs")
-    (version "1.0.6")
+    (version "1.0.7")
     (source
       (origin
         (method url-fetch)
@@ -1110,7 +1110,7 @@ synchronization between the X server and direct-rendering clients.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1mxfsvj9m3pn8cdkcn4kg190zp665mf4pv0083g6xykvsgxzq1wh"))))
+            "1wy4km3qwwajbyl8y9pka0zwizn7d9pfiyjgzba02x3a083lr79f"))))
     (build-system gnu-build-system)
     (inputs
       `(("xtrans" ,xtrans)
@@ -1272,7 +1272,7 @@ with the Cygwin XWin server when running X11 in a rootless mode.")
 (define-public libxdmcp
   (package
     (name "libxdmcp")
-    (version "1.1.1")
+    (version "1.1.2")
     (source
       (origin
         (method url-fetch)
@@ -1282,7 +1282,7 @@ with the Cygwin XWin server when running X11 in a rootless mode.")
                ".tar.bz2"))
         (sha256
           (base32
-            "13highx4xpgkiwykpcl7z2laslrjc4pzi4h617ny9p7r6116vkls"))))
+            "1qp4yhxbfnpj34swa0fj635kkihdkwaiw7kf55cg5zqqg630kzl1"))))
     (build-system gnu-build-system)
     (inputs
       `(("xproto" ,xproto)))
@@ -1331,7 +1331,7 @@ configuration files.")
 (define-public libxkbfile
   (package
     (name "libxkbfile")
-    (version "1.0.8")
+    (version "1.0.9")
     (source
       (origin
         (method url-fetch)
@@ -1341,7 +1341,7 @@ configuration files.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0flg5arw6n3njagmsi4i4l0zl5bfx866a1h9ydc3bi1pqlclxaca"))))
+            "0smimr14zvail7ar68n7spvpblpdnih3jxrva7cpa6cn602px0ai"))))
     (build-system gnu-build-system)
     (inputs
       `(("libx11" ,libx11)))
@@ -1557,7 +1557,7 @@ input from UTF-8 into the locale's encoding.")
 (define-public mkfontscale
   (package
     (name "mkfontscale")
-    (version "1.1.1")
+    (version "1.1.2")
     (source
       (origin
         (method url-fetch)
@@ -1567,7 +1567,7 @@ input from UTF-8 into the locale's encoding.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0cdpn1ii2iw1vg2ga4w62acrh78gzgf0vza4g8wx5kkp4jcifh14"))))
+            "081z8lwh9c1gyrx3ad12whnpv3jpfbqsc366mswpfm48mwl54vcc"))))
     (build-system gnu-build-system)
     (inputs
       `(("zlib" ,zlib)
@@ -1636,7 +1636,7 @@ network-transparent printing system.")
 (define-public randrproto
   (package
     (name "randrproto")
-    (version "1.4.0")
+    (version "1.5.0")
     (source
       (origin
         (method url-fetch)
@@ -1646,7 +1646,7 @@ network-transparent printing system.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1kq9h93qdnniiivry8jmhlgwn9fbx9xp5r9cmzfihlx5cs62xi45"))))
+            "0s4496z61y5q45q20gldwpf788b9nsa8hb13gnck1mwwwwrmarsc"))))
     (build-system gnu-build-system)
     (native-inputs `(("pkg-config" ,pkg-config)))
     (home-page "http://www.x.org/wiki/")
@@ -1757,7 +1757,7 @@ features and to query screensaver info on specific windows.")
 (define-public sessreg
   (package
     (name "sessreg")
-    (version "1.0.8")
+    (version "1.1.0")
     (source
       (origin
         (method url-fetch)
@@ -1767,7 +1767,7 @@ features and to query screensaver info on specific windows.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1hy4wvgawajf4qw2k51fkcjzxw0drx60ydzpmqhj7k1g4z3cqahf"))))
+            "0z013rskwmdadd8cdlxvh4asmgim61qijyzfbqmr1q1mg1jpf4am"))))
     (build-system gnu-build-system)
     (inputs
       `(("xproto" ,xproto)))
@@ -1785,7 +1785,7 @@ used with other display managers such as gdm or kdm.")
 (define-public setxkbmap
   (package
     (name "setxkbmap")
-    (version "1.3.0")
+    (version "1.3.1")
     (source
       (origin
         (method url-fetch)
@@ -1795,7 +1795,7 @@ used with other display managers such as gdm or kdm.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1inygpvlgc6vr5h9laxw9lnvafnccl3fy0g5n9ll28iq3yfmqc1x"))))
+            "1qfk097vjysqb72pq89h0la3462kbb2dh1d11qzs2fr67ybb7pd9"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxkbfile" ,libxkbfile)
@@ -1820,7 +1820,7 @@ listed on the command line.")
 (define-public smproxy
   (package
     (name "smproxy")
-    (version "1.0.5")
+    (version "1.0.6")
     (source
       (origin
         (method url-fetch)
@@ -1830,7 +1830,7 @@ listed on the command line.")
                ".tar.bz2"))
         (sha256
           (base32
-            "02fn5wa1gs2jap6sr9j9yk6zsvz82j8l61pf74iyqwa99q4wnb67"))))
+            "0rkjyzmsdqmlrkx8gy2j4q6iksk58hcc92xzdprkf8kml9ar3wbc"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxt" ,libxt)
@@ -1939,7 +1939,7 @@ server.")
 (define-public x11perf
   (package
     (name "x11perf")
-    (version "1.5.4")
+    (version "1.6.0")
     (source
       (origin
         (method url-fetch)
@@ -1949,7 +1949,7 @@ server.")
                ".tar.bz2"))
         (sha256
           (base32
-            "111iwpxhnxjiq44w96zf0kszg5zpgv1g3ayx18v4nhdzl9bqivi4"))))
+            "0lb716yfdb8f11h4cz93d1bapqdxf1xplsb21kbp4xclq7g9hw78"))))
     (build-system gnu-build-system)
     (inputs
       `(("libx11" ,libx11)
@@ -2112,7 +2112,7 @@ to query the server for available resource IDs.")
 (define-public xcmsdb
   (package
     (name "xcmsdb")
-    (version "1.0.4")
+    (version "1.0.5")
     (source
       (origin
         (method url-fetch)
@@ -2122,7 +2122,7 @@ to query the server for available resource IDs.")
                ".tar.bz2"))
         (sha256
           (base32
-            "03ms731l3kvaldq7ycbd30j6134b61i3gbll4b2gl022wyzbjq74"))))
+            "1ik7gzlp2igz183x70883000ygp99r20x3aah6xhaslbpdhm6n75"))))
     (build-system gnu-build-system)
     (inputs
       `(("libx11" ,libx11)))
@@ -2201,7 +2201,7 @@ X server: 'handhelds', 'redglass' and 'whiteglass'.")
 (define-public xdpyinfo
   (package
     (name "xdpyinfo")
-    (version "1.3.1")
+    (version "1.3.2")
     (source
       (origin
         (method url-fetch)
@@ -2211,7 +2211,7 @@ X server: 'handhelds', 'redglass' and 'whiteglass'.")
                ".tar.bz2"))
         (sha256
           (base32
-            "154b29zlrq33lmni883jgwyrb2kx7z8h52jx1s3ys5x5d582iydf"))))
+            "0ldgrj4w2fa8jng4b3f3biaj0wyn8zvya88pnk70d7k12pcqw8rh"))))
     (build-system gnu-build-system)
     (inputs
       `(("inputproto" ,inputproto)
@@ -2240,7 +2240,7 @@ available.")
 (define-public xdriinfo
   (package
     (name "xdriinfo")
-    (version "1.0.4")
+    (version "1.0.5")
     (source
       (origin
         (method url-fetch)
@@ -2250,7 +2250,7 @@ available.")
                ".tar.bz2"))
         (sha256
           (base32
-            "076bjix941znyjmh3j5jjsnhp2gv2iq53d0ks29mvvv87cyy9iim"))))
+            "0681d0y8liqakkpz7mmsf689jcxrvs5291r20qi78mc9xxk3gfjc"))))
     (build-system gnu-build-system)
     (inputs
       `(("mesa" ,mesa)
@@ -2268,7 +2268,7 @@ DRI (Direct Rendering Infrastructure) drivers.")
 (define-public xev
   (package
     (name "xev")
-    (version "1.2.1")
+    (version "1.2.2")
     (source
       (origin
         (method url-fetch)
@@ -2278,7 +2278,7 @@ DRI (Direct Rendering Infrastructure) drivers.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0hv296mysglcgkx6lj1wxc23kshb2kix1a8yqppxj5vz16mpzw8i"))))
+            "0krivhrxpq6719103r541xpi3i3a0y15f7ypc4lnrx8sdhmfcjnr"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxrender" ,libxrender)
@@ -2333,7 +2333,7 @@ XC-APPGROUP, XTEST.")
     (source
      (origin
        (method url-fetch)
-       (uri (string-append "http://www.freedesktop.org/software/" name "/"
+       (uri (string-append "https://www.freedesktop.org/software/" name "/"
                            name "-" version ".tar.xz"))
        (sha256
         (base32
@@ -2355,7 +2355,7 @@ devices, thus making direct access unnecessary.")
 (define-public xf86-input-evdev
   (package
     (name "xf86-input-evdev")
-    (version "2.8.4")
+    (version "2.10.1")
     (source
       (origin
         (method url-fetch)
@@ -2365,11 +2365,12 @@ devices, thus making direct access unnecessary.")
                ".tar.bz2"))
         (sha256
           (base32
-            "030haki1h0m85h91c91812gdnk6znfamw5kpr010zxwwbsgxxyl5"))))
+            "05z05n39v8s2b0hwhcjb1bca7j8gc62bv9jxnibawwmjym3jp75g"))))
     (build-system gnu-build-system)
     (inputs
       `(("udev" ,eudev)
         ("libevdev" ,libevdev)
+        ("mtdev" ,mtdev)
         ("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
     (arguments
@@ -2388,7 +2389,7 @@ including most mice, keyboards, tablets and touchscreens.")
 (define-public xf86-input-libinput
   (package
     (name "xf86-input-libinput")
-    (version "0.8.0")
+    (version "0.16.0")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -2396,7 +2397,7 @@ including most mice, keyboards, tablets and touchscreens.")
                     name "-" version ".tar.bz2"))
               (sha256
                (base32
-                "0fm4vrkw7azipbnwvc2l18g65z77pllsznaajd8q3zpg9ycb0li1"))))
+                "0jbgnxsbr3g4g9vkspcc6pqy7av59zx5bb78vkvaqy8yx4qybbgx"))))
     (build-system gnu-build-system)
     (arguments
      '(#:configure-flags
@@ -2448,7 +2449,7 @@ It is used to cotrol the pointer with a joystick device.")
 (define-public xf86-input-keyboard
   (package
     (name "xf86-input-keyboard")
-    (version "1.8.0")
+    (version "1.8.1")
     (source
       (origin
         (method url-fetch)
@@ -2458,7 +2459,7 @@ It is used to cotrol the pointer with a joystick device.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0nyb61w30z32djrllgr2s1i13di3vsl6hg4pqjhxdal71971ria1"))))
+            "04d27kwqq03fc26an6051hs3i0bff8albhnngzyd59wxpwwzzj0s"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -2504,7 +2505,7 @@ as USB mice.")
 (define-public xf86-input-synaptics
   (package
     (name "xf86-input-synaptics")
-    (version "1.8.1")
+    (version "1.8.3")
     (source
       (origin
         (method url-fetch)
@@ -2514,7 +2515,7 @@ as USB mice.")
                ".tar.bz2"))
         (sha256
           (base32
-            "16phzd7yhl4wns957c35qz2nahmjvnlx05jf975s524qkvrdlkyp"))))
+            "009zx199pilcvlaqm6fx4mg94q81d6vvl5rznmw3frzkfh6117yk"))))
     (build-system gnu-build-system)
     (inputs `(("libx11" ,libx11)
               ("libxi" ,libxi)
@@ -2540,7 +2541,7 @@ as USB mice.")
 (define-public xf86-input-void
   (package
     (name "xf86-input-void")
-    (version "1.4.0")
+    (version "1.4.1")
     (source
       (origin
         (method url-fetch)
@@ -2550,7 +2551,7 @@ as USB mice.")
                ".tar.bz2"))
         (sha256
           (base32
-            "01bmk324fq48wydvy1qrnxbw6qz0fjd0i80g0n4cqr1c4mjmif9a"))))
+            "171k8b8s42s3w73l7ln9jqwk88w4l7r1km2blx1vy898c854yvpr"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -2616,7 +2617,7 @@ as USB mice.")
 (define-public xf86-video-ati
   (package
     (name "xf86-video-ati")
-    (version "7.5.0")
+    (version "7.6.1")
     (source
       (origin
         (method url-fetch)
@@ -2626,7 +2627,7 @@ as USB mice.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0dkrw036ikym8aacl43lnf04q0wbms5498xg5b3l16ngnq36ygpc"))))
+            "0k6kw69mcarlmxlb4jlhz887jxqr94qx2pin04xcv2ysp3pdj5i5"))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
               ("xxf86driproto" ,xf86driproto)
@@ -2644,7 +2645,7 @@ X server.")
 (define-public xf86-video-cirrus
   (package
     (name "xf86-video-cirrus")
-    (version "1.5.2")
+    (version "1.5.3")
     (source
       (origin
         (method url-fetch)
@@ -2654,7 +2655,7 @@ X server.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1mycqgjp18b6adqj2h90vp324xh8ysyi5migfmjc914vbnkf2q9k"))))
+            "1asifc6ld2g9kap15vfhvsvyl69lj7pw3d9ra9mi4najllh7pj7d"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -2698,7 +2699,7 @@ framebuffer device.")
 (define-public xf86-video-geode
   (package
     (name "xf86-video-geode")
-    (version "2.11.16")
+    (version "2.11.18")
     (source
       (origin
         (method url-fetch)
@@ -2708,7 +2709,7 @@ framebuffer device.")
                ".tar.bz2"))
         (sha256
           (base32
-           "19y13xl7yfrgyis92rmxi0ld95ajgr5il0n9j1dridwzw9aizz1q"))
+           "1s59kdj573v38sb14xfhp1l926aypbhy11vaz36y72x6calfkv6n"))
         (patches (list (search-patch "xf86-video-geode-glibc-2.20.patch")))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
@@ -2810,45 +2811,54 @@ X server.")
 
 
 (define-public xf86-video-intel
-  (package
-    (name "xf86-video-intel")
-    (version "2.21.15")
-    (source
-      (origin
-        (method url-fetch)
-        (uri (string-append
-               "mirror://xorg/individual/driver/xf86-video-intel-"
-               version
-               ".tar.bz2"))
-        (sha256
-          (base32
-           "1z6ncmpszmwqi9xr590c4kp4gjjf7mndcr56r35x2bx7h87i8nkx"))
-        (patches (list (search-patch "xf86-video-intel-compat-api.patch")
-                       (search-patch "xf86-video-intel-glibc-2.20.patch")))))
-    (build-system gnu-build-system)
-    (inputs `(("mesa" ,mesa)
-              ("udev" ,eudev)
-              ("libx11" ,libx11)
-              ("xorg-server" ,xorg-server)))
-    (native-inputs
-     `(("pkg-config" ,pkg-config)))
-    (supported-systems
-     ;; This driver is only supported on Intel systems.
-     (filter (lambda (system) (or (string-prefix? "i686-" system)
-                                  (string-prefix? "x86_64-" system)))
-             %supported-systems))
-    (home-page "http://www.x.org/wiki/")
-    (synopsis "Intel video driver for X server")
-    (description
-     "xf86-video-intel is a 2D graphics driver for the Xorg X server.
+  (let ((commit "d167280"))
+    (package
+      (name "xf86-video-intel")
+      (version (string-append "2.99.917-1-" commit))
+      (source
+       (origin
+         ;; there's no current tarball
+         (method git-fetch)
+         (uri (git-reference
+               (url "http://anongit.freedesktop.org/git/xorg/driver/xf86-video-intel.git")
+               (commit commit)))
+         (sha256
+          (base32
+           "16hfcj11lbn6lp0hgrixidbfb7mghm1yn4lynmymm985w1gg0n72"))
+         (file-name (string-append name "-" version))))
+      (build-system gnu-build-system)
+      (inputs `(("mesa" ,mesa)
+                ("udev" ,eudev)
+                ("libx11" ,libx11)
+                ("libxfont" ,libxfont)
+                ("xorg-server" ,xorg-server)))
+      (native-inputs
+       `(("pkg-config" ,pkg-config)
+         ("autoconf" ,autoconf)
+         ("automake" ,automake)
+         ("libtool" ,libtool)))
+      (supported-systems
+       ;; This driver is only supported on Intel systems.
+       (filter (lambda (system) (or (string-prefix? "i686-" system)
+                                    (string-prefix? "x86_64-" system)))
+               %supported-systems))
+      (arguments
+       '(#:phases (modify-phases %standard-phases
+                    (add-after 'unpack 'bootstrap
+                      (lambda _
+                        (zero? (system* "autoreconf" "-vfi")))))))
+      (home-page "http://www.x.org/wiki/")
+      (synopsis "Intel video driver for X server")
+      (description
+       "xf86-video-intel is a 2D graphics driver for the Xorg X server.
 It supports a variety of Intel graphics chipsets.")
-    (license license:x11)))
+      (license license:x11))))
 
 
 (define-public xf86-video-mach64
   (package
     (name "xf86-video-mach64")
-    (version "6.9.4")
+    (version "6.9.5")
     (source
       (origin
         (method url-fetch)
@@ -2858,7 +2868,7 @@ It supports a variety of Intel graphics chipsets.")
                ".tar.bz2"))
         (sha256
           (base32
-           "0pl582vnc6hdxqhf5c0qdyanjqxb4crnhqlmxxml5a60syw0iwcp"))
+           "07xlf5nsjm0x18ij5gyy4lf8hwpl10i8chi3skpqjh84drdri61y"))
         (patches (list (search-patch "xf86-video-mach64-glibc-2.20.patch")))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
@@ -2880,7 +2890,7 @@ the same level of support for generic VGA or 8514/A adapters.")
 (define-public xf86-video-mga
   (package
     (name "xf86-video-mga")
-    (version "1.6.3")
+    (version "1.6.4")
     (source
       (origin
         (method url-fetch)
@@ -2890,8 +2900,7 @@ the same level of support for generic VGA or 8514/A adapters.")
                ".tar.bz2"))
         (sha256
           (base32
-           "1my7y67sadjjmab1dyxckylrggi7p01yk4wwg9w6k1q96pmb213p"))
-        (patches (list (search-patch "xf86-video-mga-glibc-2.20.patch")))))
+           "0kyl8w99arviv27pc349zsy2vinnm7mdpy34vr9nzisicw5nkij8"))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
               ("xf86driproto" ,xf86driproto)
@@ -2932,7 +2941,7 @@ kernel mode setting (KMS).")
 (define-public xf86-video-neomagic
   (package
     (name "xf86-video-neomagic")
-    (version "1.2.8")
+    (version "1.2.9")
     (source
       (origin
         (method url-fetch)
@@ -2942,7 +2951,7 @@ kernel mode setting (KMS).")
                ".tar.bz2"))
         (sha256
           (base32
-            "0x48sxs1p3kmwk3pq1j7vl93y59gdmgkq1x5xbnh0yal0angdash"))))
+            "1whb2kgyqaxdjim27ya404acz50izgmafwnb6y9m89q5n6b97y3j"))))
     (build-system gnu-build-system)
     (inputs `(("xf86dgaproto" ,xf86dgaproto)
               ("xorg-server" ,xorg-server)))
@@ -3012,28 +3021,20 @@ supported, and the RENDER extension is not accelerated by this driver.")
 (define-public xf86-video-nouveau
   (package
     (name "xf86-video-nouveau")
-    (version "1.0.11")
-    (source (origin
-              ;; There are no tarball releases of Nouveau.
-              (method git-fetch)
-              (uri (git-reference
-                    (url "git://anongit.freedesktop.org/nouveau/xf86-video-nouveau")
-                    (commit (string-append name "-" version))))
-              (sha256
-               (base32
-                "0zdb6b0n7pzf3l8j8hl7gfshg8jsmcmk11isvvl542yc36162ahp"))))
+    (version "1.0.12")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append
+             "mirror://xorg/individual/driver/xf86-video-nouveau-"
+             version
+             ".tar.bz2"))
+       (sha256
+        (base32
+         "07irv1zkk0rkyn1d7f2gn1icgcz2ix0pwv74sjian763gynmg80f"))))
     (build-system gnu-build-system)
-    (arguments
-     '(#:phases (alist-cons-after
-                 'unpack 'bootstrap
-                 (lambda _
-                   (zero? (system* "autoreconf" "-vi")))
-                 %standard-phases)))
     (inputs `(("xorg-server" ,xorg-server)))
-    (native-inputs `(("pkg-config" ,pkg-config)
-                     ("autoconf" ,(autoconf-wrapper))
-                     ("automake" ,automake)
-                     ("libtool" ,libtool)))
+    (native-inputs `(("pkg-config" ,pkg-config)))
     (home-page "http://nouveau.freedesktop.org")
     (synopsis "NVIDIA video driver for X server")
     (description
@@ -3078,7 +3079,7 @@ UniChrome Pro and Chrome9 integrated graphics processors.")
 (define-public xf86-video-r128
   (package
     (name "xf86-video-r128")
-    (version "6.9.2")
+    (version "6.10.1")
     (source
       (origin
         (method url-fetch)
@@ -3088,8 +3089,7 @@ UniChrome Pro and Chrome9 integrated graphics processors.")
                ".tar.bz2"))
         (sha256
           (base32
-           "1q3fsc603k2yinphx5rrcl5356qkpywwz8axlw277l2231gjjbcb"))
-        (patches (list (search-patch "xf86-video-r128-glibc-2.20.patch")))))
+           "1sp4glyyj23rs77vgffmn0mar5h504a86701nzvi56qwhd4yzgsy"))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
               ("xf86driproto" ,xf86driproto)
@@ -3106,7 +3106,7 @@ This driver is intended for ATI Rage 128 based cards.")
 (define-public xf86-video-savage
   (package
     (name "xf86-video-savage")
-    (version "2.3.7")
+    (version "2.3.8")
     (source
       (origin
         (method url-fetch)
@@ -3116,7 +3116,7 @@ This driver is intended for ATI Rage 128 based cards.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0i2aqp68rfkrz9c1p6d7ny9x7bjrlnby7q56zf01fb12r42l4784"))))
+            "0qzshncynjdmyhavhqw4x5ha3gwbygi0zbsy158fpg1jcnla9kpx"))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
               ("xf86driproto" ,xf86driproto)
@@ -3132,7 +3132,7 @@ This driver is intended for ATI Rage 128 based cards.")
 (define-public xf86-video-siliconmotion
   (package
     (name "xf86-video-siliconmotion")
-    (version "1.7.7")
+    (version "1.7.8")
     (source
       (origin
         (method url-fetch)
@@ -3142,10 +3142,7 @@ This driver is intended for ATI Rage 128 based cards.")
                ".tar.bz2"))
         (sha256
           (base32
-           "1an321kqvsxq0z35acwl99lc8hpdkayw0q180744ypcl8ffvbf47"))
-        (patches
-         (list
-          (search-patch "xf86-video-siliconmotion-remove-mibstore.patch")))))
+           "1sqv0y31mi4zmh9yaxqpzg7p8y2z01j6qys433hb8n4yznllkm79"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -3160,7 +3157,7 @@ Xorg X server.")
 (define-public xf86-video-sis
   (package
     (name "xf86-video-sis")
-    (version "0.10.7")
+    (version "0.10.8")
     (source
       (origin
         (method url-fetch)
@@ -3170,9 +3167,7 @@ Xorg X server.")
                ".tar.bz2"))
         (sha256
           (base32
-           "1l0w84x39gq4y9j81dny9r6rma1xkqvxpsavpkd8h7h8panbcbmy"))
-        (patches (list (search-patch "xf86-video-sis-update-api.patch")
-                       (search-patch "xf86-video-sis-fix-exa-crash.patch")))))
+           "1znkqwdyd6am23xbsfjzamq125j5rrylg5mzqky4scv9gxbz5wy8"))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
               ("xf86dgaproto" ,xf86dgaproto)
@@ -3239,7 +3234,7 @@ This driver supports SiS chipsets of 300/315/330/340 series.")
 (define-public xf86-video-tdfx
   (package
     (name "xf86-video-tdfx")
-    (version "1.4.5")
+    (version "1.4.6")
     (source
       (origin
         (method url-fetch)
@@ -3249,9 +3244,7 @@ This driver supports SiS chipsets of 300/315/330/340 series.")
                ".tar.bz2"))
         (sha256
           (base32
-           "0nfqf1c8939s21ci1g7gacwzlr4g4nnilahgz7j2bz30zfnzpmbh"))
-        (patches (list
-                  (search-patch "xf86-video-tdfx-remove-mibstore.patch")))))
+           "0dvdrhyn1iv6rr85v1c52s1gl0j1qrxgv7x0r7qn3ba0gj38i2is"))))
     (build-system gnu-build-system)
     (inputs `(("mesa" ,mesa)
               ("xf86driproto" ,xf86driproto)
@@ -3294,7 +3287,7 @@ X server.")
 (define-public xf86-video-trident
   (package
     (name "xf86-video-trident")
-    (version "1.3.6")
+    (version "1.3.7")
     (source
       (origin
         (method url-fetch)
@@ -3304,9 +3297,7 @@ X server.")
                ".tar.bz2"))
         (sha256
           (base32
-           "0141qbfsm32i0pxjyx5czpa8x8m4lvapsp4amw1qigaa0gry6n3a"))
-        (patches (list
-                  (search-patch "xf86-video-trident-remove-mibstore.patch")))))
+           "1bhkwic2acq9za4yz4bwj338cwv5mdrgr2qmgkhlj3bscbg1imgc"))))
     (build-system gnu-build-system)
     (inputs `(("xf86dgaproto" ,xf86dgaproto)
               ("xorg-server" ,xorg-server)))
@@ -3325,7 +3316,7 @@ X server.")
 (define-public xf86-video-vesa
   (package
     (name "xf86-video-vesa")
-    (version "2.3.3")
+    (version "2.3.4")
     (source
       (origin
         (method url-fetch)
@@ -3335,7 +3326,7 @@ X server.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1y5fsg0c4bgmh1cfsbnaaf388fppyy02i7mcy9vax78flkjpb2yf"))))
+            "1haiw8r1z8ihk68d0jqph2wsld13w4qkl86biq46fvyxg7cg9pbv"))))
     (build-system gnu-build-system)
     (inputs `(("xorg-server" ,xorg-server)))
     (native-inputs `(("pkg-config" ,pkg-config)))
@@ -3350,7 +3341,7 @@ X server.")
 (define-public xf86-video-vmware
   (package
     (name "xf86-video-vmware")
-    (version "13.0.2")
+    (version "13.1.0")
     (source
       (origin
         (method url-fetch)
@@ -3360,8 +3351,7 @@ X server.")
                ".tar.bz2"))
         (sha256
           (base32
-           "0m1wfsv34s4pyr5ry87yyjb2p6vmy6vyypdz5jx0sqnkx8n3vfn8"))
-        (patches (list (search-patch "xf86-video-vmware-glibc-2.20.patch")))))
+           "1k50whwnkzxam2ihc1sw456dx0pvr76naycm4qhyjxqv9d72879w"))))
     (build-system gnu-build-system)
     (inputs `(("libx11" ,libx11)
               ("libxext" ,libxext)
@@ -3389,7 +3379,16 @@ X server.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1s6p7yxmi12q4y05va53rljwyzd6ry492r1pgi7wwq6cznivhgly"))))
+           "1s6p7yxmi12q4y05va53rljwyzd6ry492r1pgi7wwq6cznivhgly"))
+        (patches
+         (list (origin
+                 (method url-fetch)
+                 (uri "https://cgit.freedesktop.org/xorg/driver/\
+xf86-video-voodoo/patch/?id=9172ae566a0e85313fc80ab62b4455393eefe593")
+                 (sha256
+                  (base32
+                   "0rndmxf5b8j3hjnhrwrnzsq5024fli134fj1mprhkcrvax2zq8db"))
+                 (file-name "xf86-video-voodoo-pcitag.patch"))))))
     (build-system gnu-build-system)
     (inputs `(("xf86dgaproto" ,xf86dgaproto)
               ("xorg-server" ,xorg-server)))
@@ -3501,7 +3500,7 @@ configuring modelines and gamma.")
 (define-public xgamma
   (package
     (name "xgamma")
-    (version "1.0.5")
+    (version "1.0.6")
     (source
       (origin
         (method url-fetch)
@@ -3511,7 +3510,7 @@ configuring modelines and gamma.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0463sawps86jnxn121ramsz4sicy3az5wa5wsq4rqm8dm3za48p3"))))
+            "1lr2nb1fhg5fk2fchqxdxyl739602ggwhmgl2wiv5c8qbidw7w8f"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxxf86vm" ,libxxf86vm)
@@ -3529,7 +3528,7 @@ monitor via the X video mode extension.")
 (define-public xhost
   (package
     (name "xhost")
-    (version "1.0.6")
+    (version "1.0.7")
     (source
       (origin
         (method url-fetch)
@@ -3539,7 +3538,7 @@ monitor via the X video mode extension.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1hlxm0is9nks1cx033s1733kkib9ivx2bxa3pb9yayqavwibkxd6"))))
+            "16n26xw6l01zq31d4qvsaz50misvizhn7iihzdn5f7s72pp1krlk"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxmu" ,libxmu)
@@ -3588,7 +3587,7 @@ alternative implementations like XRandR or TwinView.")
 (define-public xinput
   (package
     (name "xinput")
-    (version "1.6.1")
+    (version "1.6.2")
     (source
       (origin
         (method url-fetch)
@@ -3598,7 +3597,7 @@ alternative implementations like XRandR or TwinView.")
                ".tar.bz2"))
         (sha256
           (base32
-            "07w7zlpdhpwzzshg8q0y152cy3wl2fj7x1897glnp2la487jsqxp"))))
+            "1i75mviz9dyqyf7qigzmxq8vn31i86aybm662fzjz5c086dx551n"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxrender" ,libxrender)
@@ -3670,7 +3669,7 @@ make keyboards more accessible to people with physical impairments.")
 (define-public xkbevd
   (package
     (name "xkbevd")
-    (version "1.1.3")
+    (version "1.1.4")
     (source
       (origin
         (method url-fetch)
@@ -3680,7 +3679,7 @@ make keyboards more accessible to people with physical impairments.")
                ".tar.bz2"))
         (sha256
           (base32
-            "05h1xcnbalndbrryyqs8wzy9h3wz655vc0ymhlk2q4aik17licjm"))))
+            "0sprjx8i86ljk0l7ldzbz2xlk8916z5zh78cafjv8k1a63js4c14"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxkbfile" ,libxkbfile)
@@ -3734,7 +3733,7 @@ extension to the X11 protocol.  It includes:
 (define-public xkeyboard-config
   (package
     (name "xkeyboard-config")
-    (version "2.13")
+    (version "2.17")
     (source
       (origin
         (method url-fetch)
@@ -3744,7 +3743,7 @@ extension to the X11 protocol.  It includes:
               ".tar.bz2"))
         (sha256
           (base32
-            "1klzbwabzd7bhbg23b14vy4l5xgpapn8lc0m5d8h40d3p7rfjnvv"))))
+            "00878f1v3034ki78pjpf2db0bh7jsmszsnxr3bf5qxripm2bxiny"))))
     (build-system gnu-build-system)
     (inputs
       `(("gettext" ,gnu-gettext)
@@ -3795,7 +3794,7 @@ programs that have displayed undesired windows on a user's screen.")
 (define-public xlsatoms
   (package
     (name "xlsatoms")
-    (version "1.1.1")
+    (version "1.1.2")
     (source
       (origin
         (method url-fetch)
@@ -3805,7 +3804,7 @@ programs that have displayed undesired windows on a user's screen.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1y9nfl8s7njxbnci8c20j986xixharasgg40vdw92y593j6dk2rv"))))
+            "196yjik910xsr7dwy8daa0amr0r22ynfs360z0ndp9mx7mydrra7"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxcb" ,libxcb)))
@@ -3876,7 +3875,7 @@ protocol.")
 (define-public xmodmap
   (package
     (name "xmodmap")
-    (version "1.0.8")
+    (version "1.0.9")
     (source
       (origin
         (method url-fetch)
@@ -3886,7 +3885,7 @@ protocol.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1hwzm54m4ng09ls9i4bq0x84zbyhamgzasgrvhxxp8jqk34f7qpg"))
+            "0y649an3jqfq9klkp9y5gj20xb78fw6g193f5mnzpl0hbz6fbc5p"))
         (patches (list (search-patch "xmodmap-asprintf.patch")))))
     (build-system gnu-build-system)
     (inputs
@@ -4170,7 +4169,7 @@ libICE, the X font server, and related components.")
 (define-public xvinfo
   (package
     (name "xvinfo")
-    (version "1.1.2")
+    (version "1.1.3")
     (source
       (origin
         (method url-fetch)
@@ -4180,7 +4179,7 @@ libICE, the X font server, and related components.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1qsh7fszi727l3vwlaf9pb7bpikdv15smrx5qhlgg3kqzl7xklzf"))))
+            "1sz5wqhxd1fqsfi1w5advdlwzkizf2fgl12hdpk66f7mv9l8pflz"))))
     (build-system gnu-build-system)
     (inputs
       `(("libxext" ,libxext)
@@ -4406,7 +4405,7 @@ cannot be adequately worked around on the client side of the wire.")
 (define-public libxp
   (package
     (name "libxp")
-    (version "1.0.2")
+    (version "1.0.3")
     (source
       (origin
         (method url-fetch)
@@ -4416,7 +4415,7 @@ cannot be adequately worked around on the client side of the wire.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1dfh5w8sjz5b5fl6dl4y63ckq99snslz7bir8zq2rg8ax6syabwm"))))
+            "0mwc2jwmq03b1m9ihax5c6gw2ln8rc70zz4fsj3kb7440nchqdkz"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("printproto" ,printproto)))
@@ -4434,7 +4433,7 @@ cannot be adequately worked around on the client side of the wire.")
 (define-public libxrender
   (package
     (name "libxrender")
-    (version "0.9.8")
+    (version "0.9.9")
     (source
       (origin
         (method url-fetch)
@@ -4444,7 +4443,7 @@ cannot be adequately worked around on the client side of the wire.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0qpwyjhbpp734vnhca992pjh4w7ijslidkzx1pcwbbk000pv050x"))))
+            "06myx7044qqdswxndsmd82fpp670klnizkgzdm194h51h1wyabzw"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("renderproto" ,renderproto)))
@@ -4558,7 +4557,7 @@ script around the mkfontscale program.")
 (define-public xproto
   (package
     (name "xproto")
-    (version "7.0.26")
+    (version "7.0.28")
     (source
       (origin
         (method url-fetch)
@@ -4568,7 +4567,7 @@ script around the mkfontscale program.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0ksi8vhfd916bx2f3xlyhn6azf6cvvzrsdja26haa1cqfp0n4qb3"))))
+            "1jpnvm33vi2dar5y5zgz7jjh0m8fpkcxm0f0lbwfx37ns5l5bs19"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("util-macros" ,util-macros))) ; to get util-macros in (almost?) all package inputs
@@ -4710,7 +4709,7 @@ new API's in libXft, or the legacy API's in libX11.")
 (define-public libxi
   (package
     (name "libxi")
-    (version "1.7.4")
+    (version "1.7.6")
     (source
       (origin
         (method url-fetch)
@@ -4720,7 +4719,7 @@ new API's in libXft, or the legacy API's in libX11.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0i12lj973grlp9fa79v0vh9cahk3nf9csdjnf81iip0qcrlc5zrc"))))
+            "1b5p0l19ynmd6blnqr205wyngh6fagl35nqb4v05dw60rr9aachz"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("inputproto" ,inputproto)
@@ -4740,7 +4739,7 @@ new API's in libXft, or the legacy API's in libX11.")
 (define-public libxrandr
   (package
     (name "libxrandr")
-    (version "1.4.2")
+    (version "1.5.0")
     (source
       (origin
         (method url-fetch)
@@ -4750,7 +4749,7 @@ new API's in libXft, or the legacy API's in libX11.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1b95p3l84ppv6j7dbbmg0zrz6k8xdwvnag1l6ajm3gk9qwdb79ya"))))
+            "0n6ycs1arf4wb1cal9il6v7vbxbf21qhs9sbfl8xndgwnxclk1kg"))))
     (build-system gnu-build-system)
     (propagated-inputs
       ;; In accordance with xrandr.pc.
@@ -4771,7 +4770,7 @@ new API's in libXft, or the legacy API's in libX11.")
 (define-public libxvmc
   (package
     (name "libxvmc")
-    (version "1.0.8")
+    (version "1.0.9")
     (source
       (origin
         (method url-fetch)
@@ -4781,7 +4780,7 @@ new API's in libXft, or the legacy API's in libX11.")
                ".tar.bz2"))
         (sha256
           (base32
-            "015jk3bxfmj6zaw99x282f9npi8qqaw34yg186frags3z8g406jy"))))
+            "0mjp1b21dvkaz7r0iq085r92nh5vkpmx99awfgqq9hgzyvgxf0q7"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("libxv" ,libxv)))
@@ -4800,7 +4799,7 @@ new API's in libXft, or the legacy API's in libX11.")
 (define-public libxxf86vm
   (package
     (name "libxxf86vm")
-    (version "1.1.3")
+    (version "1.1.4")
     (source
       (origin
         (method url-fetch)
@@ -4810,7 +4809,7 @@ new API's in libXft, or the legacy API's in libX11.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1f1pxj018nk7ybxv58jmn5y8gm2288p4q3l2dng9n1p25v1qcpns"))))
+            "0mydhlyn72i7brjwypsqrpkls3nm6vxw0li8b2nw0caz7kwjgvmg"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("libxext" ,libxext)
@@ -4876,7 +4875,7 @@ over Xlib, including:
 (define-public xorg-server
   (package
     (name "xorg-server")
-    (version "1.16.4")
+    (version "1.18.1")
     (source
       (origin
         (method url-fetch)
@@ -4885,7 +4884,7 @@ over Xlib, including:
               name "-" version ".tar.bz2"))
         (sha256
          (base32
-          "0wf8xykcjhvpk9ppjcixvf60p6kkyrpmfj0z29d93a8kjb6f3dmb"))))
+          "17bq40als48v12ld81jysc0gj5g572zkjkyzbhlm3ac9xgdmdv45"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("dri2proto" ,dri2proto)
@@ -4986,7 +4985,7 @@ draggable titlebars and borders.")
 (define-public libx11
   (package
     (name "libx11")
-    (version "1.6.2")
+    (version "1.6.3")
     (source
       (origin
         (method url-fetch)
@@ -4996,7 +4995,7 @@ draggable titlebars and borders.")
                ".tar.bz2"))
         (sha256
           (base32
-            "05mx0s0vqzds3qjc1gmjr2s6x2ll37z4lfhgm7p2w7936zl2g81a"))))
+            "04c1vj53xq2xgyxx5vhln3wm2d76hh1n95fvs3myhligkz1sfcfg"))))
     (build-system gnu-build-system)
     (outputs '("out"
                "doc"))                            ;8 MiB of man pages + XML
@@ -5052,7 +5051,7 @@ draggable titlebars and borders.")
 (define-public libxt
   (package
     (name "libxt")
-    (version "1.1.4")
+    (version "1.1.5")
     (source
       (origin
         (method url-fetch)
@@ -5062,7 +5061,7 @@ draggable titlebars and borders.")
                ".tar.bz2"))
         (sha256
           (base32
-            "0myxwbx9ylam5x3ia5b5f4x8azcqdm420h9ad1r4hrgmi2lrffl4"))))
+            "06lz6i7rbrp19kgikpaz4c97fw7n31k2h2aiikczs482g2zbdvj6"))))
     (build-system gnu-build-system)
     (outputs '("out"
                "doc"))                            ;2 MiB of man pages + XML
@@ -5087,7 +5086,7 @@ draggable titlebars and borders.")
 (define-public libxaw
   (package
     (name "libxaw")
-    (version "1.0.12")
+    (version "1.0.13")
     (source
       (origin
         (method url-fetch)
@@ -5097,7 +5096,7 @@ draggable titlebars and borders.")
                ".tar.bz2"))
         (sha256
           (base32
-            "1xnv7jy86j9vhmw74frkzcraynqbw1p1s79jasargsgwfi433z4n"))))
+            "1kdhxplwrn43d9jp3v54llp05kwx210lrsdvqb6944jp29rhdy4f"))))
     (build-system gnu-build-system)
     (propagated-inputs
       `(("libxext" ,libxext)
@@ -5158,7 +5157,7 @@ The XCB util module provides the following libraries:
     (version "0.1.2")
     (source (origin
               (method url-fetch)
-              (uri (string-append "http://xcb.freedesktop.org/dist/"
+              (uri (string-append "https://xcb.freedesktop.org/dist/"
                                   "xcb-util-cursor-" version ".tar.gz"))
               (sha256
                (base32
diff --git a/gnu/packages/yasm.scm b/gnu/packages/yasm.scm
index abf6663187..31a9083cdf 100644
--- a/gnu/packages/yasm.scm
+++ b/gnu/packages/yasm.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -28,7 +29,7 @@
 (define-public yasm
   (package
     (name "yasm")
-    (version "1.2.0")
+    (version "1.3.0")
     (source
      (origin
       (method url-fetch)
@@ -36,7 +37,7 @@
                           version ".tar.gz"))
       (sha256
        (base32
-        "0cfg7ji3ia2in628w42wrfvw2ixmmm4rghwmv2k202mraysgm3vn"))))
+        "0gv0slmm0qpq91za3v2v9glff3il594x5xsrbgab7xcmnh0ndkix"))))
     (build-system gnu-build-system)
     (inputs
      `(("python" ,python-wrapper)
diff --git a/gnu/packages/yubico.scm b/gnu/packages/yubico.scm
index f2e8ff133c..469d93d0dc 100644
--- a/gnu/packages/yubico.scm
+++ b/gnu/packages/yubico.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2014 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Efraim Flashner <efraim@flashner.co.il>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -29,7 +30,7 @@
 (define-public libyubikey
   (package
     (name "libyubikey")
-    (version "1.12")
+    (version "1.13")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -37,7 +38,7 @@
                     name "-" version ".tar.gz"))
               (sha256
                (base32
-                "1f0plzmr1gwry4rfgq9q70v6qwqny009hac289ad5m6sj7vqflxr"))))
+                "009l3k2zyn06dbrlja2d4p2vfnzjhlcqxi88v02mlrnb17mx1v84"))))
     (build-system gnu-build-system)
     (synopsis "Development kit for the YubiKey authentication device")
     (description
@@ -49,7 +50,7 @@ the low-level development kit for the Yubico YubiKey authentication device.")
 (define-public ykclient
   (package
     (name "ykclient")
-    (version "2.13")
+    (version "2.15")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -57,7 +58,7 @@ the low-level development kit for the Yubico YubiKey authentication device.")
                     name "-" version ".tar.gz"))
               (sha256
                (base32
-                "1lw1j61rfjngs8vvv9m348zl4166zg24bq0dy72r44wiz79yic4j"))))
+                "05jhx9waj3pl120ddnwap1v3bjrnbfhvf3lxs2xmhpcmwzpwsqgl"))))
     (build-system gnu-build-system)
 
     ;; There's just one test, and it requires network access to access
diff --git a/gnu/packages/zsh.scm b/gnu/packages/zsh.scm
index 6d25fd4671..fba7bb19b8 100644
--- a/gnu/packages/zsh.scm
+++ b/gnu/packages/zsh.scm
@@ -64,10 +64,10 @@
                                      "Util/preconfig")
                                  (("/bin/sh") (which "sh")))))
                            %standard-phases)))
-    (native-inputs `(("autoconf", autoconf)))
-    (inputs `(("ncurses", ncurses)
-              ("pcre", pcre)
-              ("perl", perl)))
+    (native-inputs `(("autoconf" ,autoconf)))
+    (inputs `(("ncurses" ,ncurses)
+              ("pcre" ,pcre)
+              ("perl" ,perl)))
     (synopsis "Powerful shell for interactive use and scripting")
     (description "The Z shell (zsh) is a Unix shell that can be used
 as an interactive login shell and as a powerful command interpreter
diff --git a/gnu/services/databases.scm b/gnu/services/databases.scm
index 8b1420116d..6c3b829df7 100644
--- a/gnu/services/databases.scm
+++ b/gnu/services/databases.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 David Thompson <davet@gnu.org>
 ;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -56,7 +57,7 @@ host	all	all	::1/128 	trust"))
 (define %default-postgres-config
   (mixed-text-file "postgresql.conf"
                    "hba_file = '" %default-postgres-hba "'\n"
-                   "ident_file = '" %default-postgres-ident "\n"))
+                   "ident_file = '" %default-postgres-ident "'\n"))
 
 (define %postgresql-accounts
   (list (user-group (name "postgres") (system? #t))
diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index e4f0736b89..02bcf1b19f 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -378,7 +378,7 @@ site} for more information."
 (define polkit-etc-files
   (match-lambda
     (($ <polkit-configuration> polkit packages)
-     `(("polkit-1" ,(polkit-directory packages))))))
+     `(("polkit-1" ,(polkit-directory (cons polkit packages)))))))
 
 (define polkit-setuid-programs
   (match-lambda
diff --git a/gnu/services/herd.scm b/gnu/services/herd.scm
index a3a9bf0230..9cb33a9fd0 100644
--- a/gnu/services/herd.scm
+++ b/gnu/services/herd.scm
@@ -66,19 +66,19 @@ return the socket."
 command object."
   (match error
     (('error ('version 0 x ...) 'service-not-found service)
-     (report-error (_ "service '~a' could not be found")
+     (report-error (_ "service '~a' could not be found~%")
                    service))
     (('error ('version 0 x ...) 'action-not-found action service)
-     (report-error (_ "service '~a' does not have an action '~a'")
+     (report-error (_ "service '~a' does not have an action '~a'~%")
                    service action))
     (('error ('version 0 x ...) 'action-exception action service
              key (args ...))
      (report-error (_ "exception caught while executing '~a' \
-on service '~a':")
+on service '~a':~%")
                    action service)
      (print-exception (current-error-port) #f key args))
     (('error . _)
-     (report-error (_ "something went wrong: ~s")
+     (report-error (_ "something went wrong: ~s~%")
                    error))
     (#f                                           ;not an error
      #t)))
diff --git a/gnu/services/xorg.scm b/gnu/services/xorg.scm
index a93dbfe7c4..980b5a6ba5 100644
--- a/gnu/services/xorg.scm
+++ b/gnu/services/xorg.scm
@@ -40,6 +40,7 @@
   #:use-module (srfi srfi-26)
   #:use-module (ice-9 match)
   #:export (xorg-configuration-file
+            %default-xorg-modules
             xorg-start-command
             %default-slim-theme
             %default-slim-theme-name
@@ -137,9 +138,52 @@ EndSection
   "\n"
   extra-config))
 
+(define %default-xorg-modules
+  (list xf86-video-vesa
+        xf86-video-fbdev
+        xf86-video-modesetting
+        xf86-video-cirrus
+        xf86-video-intel
+        xf86-video-mach64
+        xf86-video-nouveau
+        xf86-video-nv
+        xf86-video-sis
+        xf86-input-libinput
+        xf86-input-evdev
+        xf86-input-keyboard
+        xf86-input-mouse
+        xf86-input-synaptics))
+
+(define (xorg-configuration-directory modules)
+  "Return a directory that contains the @code{.conf} files for X.org that
+includes the @code{share/X11/xorg.conf.d} directories of each package listed
+in @var{modules}."
+  (computed-file "xorg.conf.d"
+                 #~(begin
+                     (use-modules (guix build utils)
+                                  (srfi srfi-1))
+
+                     (define files
+                       (append-map (lambda (module)
+                                     (find-files (string-append
+                                                  module
+                                                  "/share/X11/xorg.conf.d")
+                                                 "\\.conf$"))
+                                   (list #$@modules)))
+
+                     (mkdir #$output)
+                     (for-each (lambda (file)
+                                 (symlink file
+                                          (string-append #$output "/"
+                                                         (basename file))))
+                               files)
+                     #t)
+                 #:modules '((guix build utils))))
+
 (define* (xorg-start-command #:key
                              (guile (canonical-package guile-2.0))
                              (configuration-file (xorg-configuration-file))
+                             (modules %default-xorg-modules)
                              (xorg-server xorg-server))
   "Return a derivation that builds a @var{guile} script to start the X server
 from @var{xorg-server}.  @var{configuration-file} is the server configuration
@@ -158,6 +202,7 @@ Usually the X server is started by a login manager."
                "-logverbose" "-verbose"
                "-xkbdir" (string-append #$xkeyboard-config "/share/X11/xkb")
                "-config" #$configuration-file
+               "-configdir" #$(xorg-configuration-directory modules)
                "-nolisten" "tcp" "-terminate"
 
                ;; Note: SLiM and other display managers add the
diff --git a/gnu/system.scm b/gnu/system.scm
index 9540324df0..d600d3a293 100644
--- a/gnu/system.scm
+++ b/gnu/system.scm
@@ -1,7 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
+;;; Copyright © 2015, 2016 Alex Kost <alezost@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -362,6 +362,7 @@ explicitly appear in OS."
          ;; many people are familiar with, so keep it around.
          iw wireless-tools
 
+         iproute
          net-tools                        ; XXX: remove when Inetutils suffices
          man-db
          texinfo                               ;for the standalone Info reader
@@ -669,18 +670,31 @@ hardware-related operations as necessary when booting a Linux container."
                                            #:mapped-devices mapped-devices)))
     (return #~(string-append #$initrd "/initrd"))))
 
+(define (locale-name->definition* name)
+  "Variant of 'locale-name->definition' that raises an error upon failure."
+  (match (locale-name->definition name)
+    (#f
+     (raise (condition
+             (&message
+              (message (format #f (_ "~a: invalid locale name") name))))))
+    (def def)))
+
 (define (operating-system-locale-directory os)
   "Return the directory containing the locales compiled for the definitions
 listed in OS.  The C library expects to find it under
 /run/current-system/locale."
-  ;; While we're at it, check whether the locale of OS is defined.
-  (unless (member (operating-system-locale os)
-                  (map locale-definition-name
-                       (operating-system-locale-definitions os)))
-    (raise (condition
-            (&message (message "system locale lacks a definition")))))
-
-  (locale-directory (operating-system-locale-definitions os)
+  (define name
+    (operating-system-locale os))
+
+  (define definitions
+    ;; While we're at it, check whether NAME is defined and add it if needed.
+    (if (member name (map locale-definition-name
+                          (operating-system-locale-definitions os)))
+        (operating-system-locale-definitions os)
+        (cons (locale-name->definition* name)
+              (operating-system-locale-definitions os))))
+
+  (locale-directory definitions
                     #:libcs (operating-system-locale-libcs os)))
 
 (define (kernel->grub-label kernel)
diff --git a/gnu/system/install.scm b/gnu/system/install.scm
index 0cfc8fa5c9..b380716b69 100644
--- a/gnu/system/install.scm
+++ b/gnu/system/install.scm
@@ -237,7 +237,12 @@ the user's target storage device rather than on the RAM disk."
   ;; Minimal in-memory caching policy for nscd.
   (list (nscd-cache (database 'hosts)
                     (positive-time-to-live (* 3600 12))
-                    (negative-time-to-live 20)
+
+                    ;; Do not cache lookup failures at all since they are
+                    ;; quite likely (for instance when someone tries to ping a
+                    ;; host before networking is functional.)
+                    (negative-time-to-live 0)
+
                     (persistent? #f)
                     (max-database-size (* 5 (expt 2 20)))))) ;5 MiB
 
@@ -365,6 +370,7 @@ Use Alt-F2 for documentation.
                      parted ddrescue
                      grub                  ;mostly so xrefs to its manual work
                      cryptsetup
+                     btrfs-progs
                      wireless-tools iw wpa-supplicant-minimal iproute
                      ;; XXX: We used to have GNU fdisk here, but as of version
                      ;; 2.0.0a, that pulls Guile 1.8, which takes unreasonable
diff --git a/gnu/system/locale.scm b/gnu/system/locale.scm
index e798827a01..f9d713e0cf 100644
--- a/gnu/system/locale.scm
+++ b/gnu/system/locale.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -33,6 +33,7 @@
             locale-definition-source
             locale-definition-charset
 
+            locale-name->definition
             locale-directory
 
             %default-locale-libcs
@@ -52,6 +53,35 @@
   (charset locale-definition-charset              ;string--e.g., "UTF-8"
            (default "UTF-8")))
 
+(define %not-dot
+  (char-set-complement (char-set #\.)))
+
+(define (denormalize-codeset codeset)
+  "Attempt to guess the \"real\" name of CODESET, a normalized codeset as
+defined in (info \"(libc) Using gettextized software\")."
+  (cond ((string=? codeset "utf8")
+         "UTF-8")
+        ((string-prefix? "iso8859" codeset)
+         (string-append "ISO-8859-" (string-drop codeset 7)))
+        ((string=? codeset "eucjp")
+         "EUC-JP")
+        (else                                ;cross fingers, hope for the best
+         codeset)))
+
+(define (locale-name->definition name)
+  "Return a <locale-definition> corresponding to NAME, guessing the charset,
+or #f on failure."
+  (match (string-tokenize name %not-dot)
+    ((source charset)
+     ;; XXX: NAME is supposed to use the "normalized codeset", such as "utf8",
+     ;; whereas the actual name used is different.  Add a special case to make
+     ;; the right guess for UTF-8.
+     (locale-definition (name name)
+                        (source source)
+                        (charset (denormalize-codeset charset))))
+    (_
+     #f)))
+
 (define* (localedef-command locale
                             #:key (libc (canonical-package glibc)))
   "Return a gexp that runs 'localedef' from LIBC to build LOCALE."
diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm
index a7c03bda17..58a476a468 100644
--- a/gnu/system/vm.scm
+++ b/gnu/system/vm.scm
@@ -1,5 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
+;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -457,7 +459,13 @@ with '-virtfs' options for the host file systems listed in SHARED-FS."
                      "\" "))
 
   #~(string-append
-     " -enable-kvm -no-reboot -net nic,model=virtio \
+     ;; Only enable kvm if we see /dev/kvm exists.
+     ;; This allows users without hardware virtualization to still use these
+     ;; commands.
+     #$(if (file-exists? "/dev/kvm")
+           " -enable-kvm "
+           "")
+     " -no-reboot -net nic,model=virtio \
   " #$@(map virtfs-option shared-fs) " \
   -net user \
   -serial stdio -vga std \
diff --git a/guix/derivations.scm b/guix/derivations.scm
index 5db739a97d..1164774009 100644
--- a/guix/derivations.scm
+++ b/guix/derivations.scm
@@ -85,21 +85,11 @@
             derivation-path->output-paths
             derivation
 
-            graft
-            graft?
-            graft-origin
-            graft-replacement
-            graft-origin-output
-            graft-replacement-output
-            graft-derivation
-
             map-derivation
 
             build-derivations
             built-derivations
 
-            %graft?
-            set-grafting
 
             build-expression->derivation)
 
@@ -1111,81 +1101,6 @@ they can refer to each other."
                                   #:guile-for-build guile
                                   #:local-build? #t)))
 
-(define-record-type* <graft> graft make-graft
-  graft?
-  (origin             graft-origin)               ;derivation | store item
-  (origin-output      graft-origin-output         ;string | #f
-                      (default "out"))
-  (replacement        graft-replacement)          ;derivation | store item
-  (replacement-output graft-replacement-output    ;string | #f
-                      (default "out")))
-
-(define* (graft-derivation store name drv grafts
-                           #:key (guile (%guile-for-build))
-                           (system (%current-system)))
-  "Return a derivation called NAME, based on DRV but with all the GRAFTS
-applied."
-  ;; XXX: Someday rewrite using gexps.
-  (define mapping
-    ;; List of store item pairs.
-    (map (match-lambda
-          (($ <graft> source source-output target target-output)
-           (cons (if (derivation? source)
-                     (derivation->output-path source source-output)
-                     source)
-                 (if (derivation? target)
-                     (derivation->output-path target target-output)
-                     target))))
-         grafts))
-
-  (define outputs
-    (match (derivation-outputs drv)
-      (((names . outputs) ...)
-       (map derivation-output-path outputs))))
-
-  (define output-names
-    (match (derivation-outputs drv)
-      (((names . outputs) ...)
-       names)))
-
-  (define build
-    `(begin
-       (use-modules (guix build graft)
-                    (guix build utils)
-                    (ice-9 match))
-
-       (let ((mapping ',mapping))
-         (for-each (lambda (input output)
-                     (format #t "grafting '~a' -> '~a'...~%" input output)
-                     (force-output)
-                     (rewrite-directory input output
-                                        `((,input . ,output)
-                                          ,@mapping)))
-                   ',outputs
-                   (match %outputs
-                     (((names . files) ...)
-                      files))))))
-
-  (define add-label
-    (cut cons "x" <>))
-
-  (match grafts
-    ((($ <graft> sources source-outputs targets target-outputs) ...)
-     (let ((sources (zip sources source-outputs))
-           (targets (zip targets target-outputs)))
-       (build-expression->derivation store name build
-                                     #:system system
-                                     #:guile-for-build guile
-                                     #:modules '((guix build graft)
-                                                 (guix build utils))
-                                     #:inputs `(,@(map (lambda (out)
-                                                         `("x" ,drv ,out))
-                                                       output-names)
-                                                ,@(append (map add-label sources)
-                                                          (map add-label targets)))
-                                     #:outputs output-names
-                                     #:local-build? #t)))))
-
 (define* (build-expression->derivation store name exp ;deprecated
                                        #:key
                                        (system (%current-system))
@@ -1353,16 +1268,3 @@ ALLOWED-REFERENCES, LOCAL-BUILD?, and SUBSTITUTABLE?."
 
 (define built-derivations
   (store-lift build-derivations))
-
-;; The following might feel more at home in (guix packages) but since (guix
-;; gexp), which is a lower level, needs them, we put them here.
-
-(define %graft?
-  ;; Whether to honor package grafts by default.
-  (make-parameter #t))
-
-(define (set-grafting enable?)
-  "This monadic procedure enables grafting when ENABLE? is true, and disables
-it otherwise.  It returns the previous setting."
-  (lambda (store)
-    (values (%graft? enable?) store)))
diff --git a/guix/download.scm b/guix/download.scm
index 204cfc0826..88f285dc0a 100644
--- a/guix/download.scm
+++ b/guix/download.scm
@@ -1,6 +1,7 @@
 ;;; 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, 2014, 2015 Andreas Enge <andreas@enge.fr>
+;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -31,6 +32,7 @@
   #:use-module (srfi srfi-26)
   #:export (%mirrors
             url-fetch
+            url-fetch/tarbomb
             download-to-store))
 
 ;;; Commentary:
@@ -294,6 +296,31 @@ in the store."
                             ;; <https://bugs.gnu.org/18747>.)
                             #:local-build? #t)))))
 
+(define* (url-fetch/tarbomb url hash-algo hash
+                            #:optional name
+                            #:key (system (%current-system))
+                            (guile (default-guile)))
+  "Similar to 'url-fetch' but unpack the file from URL in a directory of its
+own.  This helper makes it easier to deal with \"tar bombs\"."
+  (define gzip
+    (module-ref (resolve-interface '(gnu packages compression)) 'gzip))
+  (define tar
+    (module-ref (resolve-interface '(gnu packages base)) 'tar))
+
+  (mlet %store-monad ((drv (url-fetch url hash-algo hash
+                                      (string-append "tarbomb-" name)
+                                      #:system system
+                                      #:guile guile)))
+    ;; Take the tar bomb, and simply unpack it as a directory.
+    (gexp->derivation name
+                      #~(begin
+                          (mkdir #$output)
+                          (setenv "PATH" (string-append #$gzip "/bin"))
+                          (chdir #$output)
+                          (zero? (system* (string-append #$tar "/bin/tar")
+                                          "xf" #$drv)))
+                      #:local-build? #t)))
+
 (define* (download-to-store store url #:optional (name (basename url))
                             #:key (log (current-error-port)) recursive?)
   "Download from URL to STORE, either under NAME or URL's basename if
diff --git a/guix/gexp.scm b/guix/gexp.scm
index 35adc179a1..87bc316f97 100644
--- a/guix/gexp.scm
+++ b/guix/gexp.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -20,6 +20,7 @@
   #:use-module (guix store)
   #:use-module (guix monads)
   #:use-module (guix derivations)
+  #:use-module (guix grafts)
   #:use-module (guix utils)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-9)
diff --git a/guix/gnu-maintenance.scm b/guix/gnu-maintenance.scm
index 96fbfb76b4..9d720ca030 100644
--- a/guix/gnu-maintenance.scm
+++ b/guix/gnu-maintenance.scm
@@ -33,6 +33,7 @@
   #:use-module (guix records)
   #:use-module (guix upstream)
   #:use-module (guix packages)
+  #:use-module (gnu packages)
   #:export (gnu-package-name
             gnu-package-mundane-name
             gnu-package-copyright-holder
@@ -57,7 +58,8 @@
             gnu-package-name->name+version
 
             %gnu-updater
-            %gnome-updater))
+            %gnome-updater
+            %xorg-updater))
 
 ;;; Commentary:
 ;;;
@@ -508,6 +510,32 @@ elpa.gnu.org, and all the GNOME packages."
                        ;; checksums.
                        #:file->signature (const #f))))
 
+(define (xorg-package? package)
+  "Return true if PACKAGE is an X.org package, developed by X.org."
+  (define xorg-uri?
+    (match-lambda
+      ((? string? uri)
+       (string-prefix? "mirror://xorg/" uri))
+      (_
+       #f)))
+
+  (match (package-source package)
+    ((? origin? origin)
+     (match (origin-uri origin)
+       ((? xorg-uri?) #t)
+       (_              #f)))
+    (_ #f)))
+
+(define (latest-xorg-release package)
+  "Return the latest release of PACKAGE, the name of an X.org package."
+  (let ((uri (string->uri (origin-uri (package-source (specification->package package))))))
+    (false-if-ftp-error
+     (latest-ftp-release
+      package
+      #:server "ftp.freedesktop.org"
+      #:directory
+      (string-append "/pub/xorg/" (dirname (uri-path uri)))))))
+
 (define %gnu-updater
   (upstream-updater
    (name 'gnu)
@@ -522,4 +550,11 @@ elpa.gnu.org, and all the GNOME packages."
    (pred gnome-package?)
    (latest latest-gnome-release)))
 
+(define %xorg-updater
+  (upstream-updater
+   (name 'xorg)
+   (description "Updater for X.org packages")
+   (pred xorg-package?)
+   (latest latest-xorg-release)))
+
 ;;; gnu-maintenance.scm ends here
diff --git a/guix/grafts.scm b/guix/grafts.scm
new file mode 100644
index 0000000000..a1f7d8801a
--- /dev/null
+++ b/guix/grafts.scm
@@ -0,0 +1,146 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2014, 2015, 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 (guix grafts)
+  #:use-module (guix records)
+  #:use-module (guix derivations)
+  #:use-module ((guix utils) #:select (%current-system))
+  #:use-module (srfi srfi-1)
+  #:use-module (srfi srfi-9 gnu)
+  #:use-module (srfi srfi-26)
+  #:use-module (ice-9 match)
+  #:export (graft?
+            graft
+            graft-origin
+            graft-replacement
+            graft-origin-output
+            graft-replacement-output
+
+            graft-derivation
+
+            %graft?
+            set-grafting))
+
+(define-record-type* <graft> graft make-graft
+  graft?
+  (origin             graft-origin)               ;derivation | store item
+  (origin-output      graft-origin-output         ;string | #f
+                      (default "out"))
+  (replacement        graft-replacement)          ;derivation | store item
+  (replacement-output graft-replacement-output    ;string | #f
+                      (default "out")))
+
+(define (write-graft graft port)
+  "Write a concise representation of GRAFT to PORT."
+  (define (->string thing output)
+    (if (derivation? thing)
+        (derivation->output-path thing output)
+        thing))
+
+  (match graft
+    (($ <graft> origin origin-output replacement replacement-output)
+     (format port "#<graft ~a ==> ~a ~a>"
+             (->string origin origin-output)
+             (->string replacement replacement-output)
+             (number->string (object-address graft) 16)))))
+
+(set-record-type-printer! <graft> write-graft)
+
+(define* (graft-derivation store drv grafts
+                           #:key
+                           (name (derivation-name drv))
+                           (guile (%guile-for-build))
+                           (system (%current-system)))
+  "Return a derivation called NAME, based on DRV but with all the GRAFTS
+applied."
+  ;; XXX: Someday rewrite using gexps.
+  (define mapping
+    ;; List of store item pairs.
+    (map (match-lambda
+          (($ <graft> source source-output target target-output)
+           (cons (if (derivation? source)
+                     (derivation->output-path source source-output)
+                     source)
+                 (if (derivation? target)
+                     (derivation->output-path target target-output)
+                     target))))
+         grafts))
+
+  (define outputs
+    (match (derivation-outputs drv)
+      (((names . outputs) ...)
+       (map derivation-output-path outputs))))
+
+  (define output-names
+    (match (derivation-outputs drv)
+      (((names . outputs) ...)
+       names)))
+
+  (define build
+    `(begin
+       (use-modules (guix build graft)
+                    (guix build utils)
+                    (ice-9 match))
+
+       (let ((mapping ',mapping))
+         (for-each (lambda (input output)
+                     (format #t "grafting '~a' -> '~a'...~%" input output)
+                     (force-output)
+                     (rewrite-directory input output
+                                        `((,input . ,output)
+                                          ,@mapping)))
+                   ',outputs
+                   (match %outputs
+                     (((names . files) ...)
+                      files))))))
+
+  (define add-label
+    (cut cons "x" <>))
+
+  (match grafts
+    ((($ <graft> sources source-outputs targets target-outputs) ...)
+     (let ((sources (zip sources source-outputs))
+           (targets (zip targets target-outputs)))
+       (build-expression->derivation store name build
+                                     #:system system
+                                     #:guile-for-build guile
+                                     #:modules '((guix build graft)
+                                                 (guix build utils))
+                                     #:inputs `(,@(map (lambda (out)
+                                                         `("x" ,drv ,out))
+                                                       output-names)
+                                                ,@(append (map add-label sources)
+                                                          (map add-label targets)))
+                                     #:outputs output-names
+                                     #:local-build? #t)))))
+
+
+;; The following might feel more at home in (guix packages) but since (guix
+;; gexp), which is a lower level, needs them, we put them here.
+
+(define %graft?
+  ;; Whether to honor package grafts by default.
+  (make-parameter #t))
+
+(define (set-grafting enable?)
+  "This monadic procedure enables grafting when ENABLE? is true, and disables
+it otherwise.  It returns the previous setting."
+  (lambda (store)
+    (values (%graft? enable?) store)))
+
+;;; grafts.scm ends here
diff --git a/guix/http-client.scm b/guix/http-client.scm
index 31b511eb1c..2161856c63 100644
--- a/guix/http-client.scm
+++ b/guix/http-client.scm
@@ -33,6 +33,7 @@
   #:use-module (guix ui)
   #:use-module (guix utils)
   #:use-module (guix base64)
+  #:autoload   (guix hash) (sha256)
   #:use-module ((guix build utils)
                 #:select (mkdir-p dump-port))
   #:use-module ((guix build download)
@@ -280,18 +281,23 @@ Raise an '&http-get-error' condition if downloading fails."
                       string->number*)
                36))))
 
+(define (cache-file-for-uri uri)
+  "Return the name of the file in the cache corresponding to URI."
+  (let ((digest (sha256 (string->utf8 (uri->string uri)))))
+    ;; Use the "URL" alphabet because it does not contain "/".
+    (string-append (cache-directory) "/http/"
+                   (base64-encode digest 0 (bytevector-length digest)
+                                  #f #f base64url-alphabet))))
+
 (define* (http-fetch/cached uri #:key (ttl (%http-cache-ttl)) text?)
   "Like 'http-fetch', return an input port, but cache its contents in
 ~/.cache/guix.  The cache remains valid for TTL seconds."
-  (let* ((directory (string-append (cache-directory) "/http/"
-                                   (uri-host uri)))
-         (file      (string-append directory "/"
-                                   (basename (uri-path uri)))))
+  (let ((file (cache-file-for-uri uri)))
     (define (update-cache)
       ;; Update the cache and return an input port.
       (let ((port (http-fetch uri #:text? text?)))
-        (mkdir-p directory)
-        (call-with-output-file file
+        (mkdir-p (dirname file))
+        (with-atomic-file-output file
           (cut dump-port port <>))
         (close-port port)
         (open-input-file file)))
diff --git a/guix/import/gem.scm b/guix/import/gem.scm
index 4b2a253130..b46622f00d 100644
--- a/guix/import/gem.scm
+++ b/guix/import/gem.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 David Thompson <davet@gnu.org>
+;;; Copryight © 2016 Ben Woodcroft <donttrustben@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -19,21 +20,33 @@
 (define-module (guix import gem)
   #:use-module (ice-9 match)
   #:use-module (ice-9 pretty-print)
+  #:use-module (srfi srfi-1)
   #:use-module (rnrs bytevectors)
   #:use-module (json)
   #:use-module (web uri)
+  #:use-module ((guix download) #:prefix download:)
   #:use-module (guix import utils)
   #:use-module (guix import json)
   #:use-module (guix packages)
+  #:use-module (guix upstream)
   #:use-module (guix licenses)
   #:use-module (guix base32)
-  #:export (gem->guix-package))
+  #:use-module (guix build-system ruby)
+  #:use-module (gnu packages)
+  #:export (gem->guix-package
+            %gem-updater))
 
 (define (rubygems-fetch name)
   "Return an alist representation of the RubyGems metadata for the package NAME,
 or #f on failure."
-  (json-fetch
-   (string-append "https://rubygems.org/api/v1/gems/" name ".json")))
+  ;; XXX: We want to silence the download progress report, which is especially
+  ;; annoying for 'guix refresh', but we have to use a file port.
+  (call-with-output-file "/dev/null"
+    (lambda (null)
+      (with-error-to-port null
+        (lambda ()
+          (json-fetch
+           (string-append "https://rubygems.org/api/v1/gems/" name ".json")))))))
 
 (define (ruby-package-name name)
   "Given the NAME of a package on RubyGems, return a Guix-compliant name for
@@ -132,3 +145,47 @@ VERSION, HASH, HOME-PAGE, DESCRIPTION, DEPENDENCIES, and LICENSES."
                                   (assoc-ref package "licenses"))))
            (make-gem-sexp name version hash home-page synopsis
                           description dependencies licenses)))))
+
+(define (guix-package->gem-name package)
+  "Given a PACKAGE built from rubygems.org, return the name of the
+package on RubyGems."
+  (let ((source-url (and=> (package-source package) origin-uri)))
+    ;; The URL has the form:
+    ;; 'https://rubygems.org/downloads/' +
+    ;; package name + '-' + version + '.gem'
+    ;; e.g. "https://rubygems.org/downloads/hashery-2.1.1.gem"
+    (substring source-url 31 (string-rindex source-url #\-))))
+
+(define (gem-package? package)
+  "Return true if PACKAGE is a gem package from RubyGems."
+
+  (define (rubygems-url? url)
+    (string-prefix? "https://rubygems.org/downloads/" url))
+
+  (let ((source-url (and=> (package-source package) origin-uri))
+        (fetch-method (and=> (package-source package) origin-method)))
+    (and (eq? fetch-method download:url-fetch)
+         (match source-url
+           ((? string?)
+            (rubygems-url? source-url))
+           ((source-url ...)
+            (any rubygems-url? source-url))))))
+
+(define (latest-release guix-package)
+  "Return an <upstream-source> for the latest release of GUIX-PACKAGE."
+  (let* ((gem-name (guix-package->gem-name
+                    (specification->package guix-package)))
+         (metadata (rubygems-fetch gem-name))
+         (version (assoc-ref metadata "version"))
+         (url (rubygems-uri gem-name version)))
+    (upstream-source
+     (package guix-package)
+     (version version)
+     (urls (list url)))))
+
+(define %gem-updater
+  (upstream-updater
+   (name 'gem)
+   (description "Updater for RubyGem packages")
+   (pred gem-package?)
+   (latest latest-release)))
diff --git a/guix/import/github.scm b/guix/import/github.scm
new file mode 100644
index 0000000000..c696dcb363
--- /dev/null
+++ b/guix/import/github.scm
@@ -0,0 +1,198 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2016 Ben Woodcroft <donttrustben@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 (guix import github)
+  #:use-module (ice-9 match)
+  #:use-module (srfi srfi-1)
+  #:use-module (json)
+  #:use-module (guix utils)
+  #:use-module ((guix download) #:prefix download:)
+  #:use-module (guix import utils)
+  #:use-module (guix packages)
+  #:use-module (guix upstream)
+  #:use-module (gnu packages)
+  #:use-module (web uri)
+  #:export (%github-updater))
+
+(define (json-fetch* url)
+  "Return a list/hash representation of the JSON resource URL, or #f on
+failure."
+  (call-with-output-file "/dev/null"
+    (lambda (null)
+      (with-error-to-port null
+        (lambda ()
+          (call-with-temporary-output-file
+           (lambda (temp port)
+             (and (url-fetch url temp)
+                  (call-with-input-file temp json->scm)))))))))
+
+(define (find-extension url)
+  "Return the extension of the archive e.g. '.tar.gz' given a URL, or
+false if none is recognized"
+  (find (lambda x (string-suffix? (first x) url))
+        (list ".tar.gz" ".tar.bz2" ".tar.xz" ".zip" ".tar")))
+
+(define (updated-github-url old-package new-version)
+  ;; Return a url for the OLD-PACKAGE with NEW-VERSION.  If no source url in
+  ;; the OLD-PACKAGE is a GitHub url, then return false.
+
+  (define (updated-url url)
+    (if (string-prefix? "https://github.com/" url)
+        (let ((ext     (find-extension url))
+              (name    (package-name old-package))
+              (version (package-version old-package))
+              (prefix  (string-append "https://github.com/"
+                                      (github-user-slash-repository url)))
+              (repo    (github-repository url)))
+          (cond
+           ((string-suffix? (string-append "/tarball/v" version) url)
+            (string-append prefix "/tarball/v" new-version))
+           ((string-suffix? (string-append "/tarball/" version) url)
+            (string-append prefix "/tarball/" new-version))
+           ((string-suffix? (string-append "/archive/v" version ext) url)
+            (string-append prefix "/archive/v" new-version ext))
+           ((string-suffix? (string-append "/archive/" version ext) url)
+            (string-append prefix "/archive/" new-version ext))
+           ((string-suffix? (string-append "/archive/" name "-" version ext)
+                            url)
+            (string-append prefix "/archive/" name "-" new-version ext))
+           ((string-suffix? (string-append "/releases/download/v" version "/"
+                                           name "-" version ext)
+                            url)
+            (string-append prefix "/releases/download/v" new-version "/" name
+                           "-" new-version ext))
+           ((string-suffix? (string-append "/releases/download/" version "/"
+                                           name "-" version ext)
+                            url)
+            (string-append prefix "/releases/download/" new-version "/" name
+                           "-" new-version ext))
+           ((string-suffix? (string-append "/releases/download/" version "/"
+                                           repo "-" version ext)
+                            url)
+            (string-append prefix "/releases/download/" new-version "/" repo
+                           "-" new-version ext))
+           ((string-suffix? (string-append "/releases/download/" repo "-"
+                                           version "/" repo "-" version ext)
+                            url)
+            (string-append "/releases/download/" repo "-" version "/" repo "-"
+                           version ext))
+           (#t #f))) ; Some URLs are not recognised.
+        #f))
+
+  (let ((source-url (and=> (package-source old-package) origin-uri))
+        (fetch-method (and=> (package-source old-package) origin-method)))
+    (if (eq? fetch-method download:url-fetch)
+        (match source-url
+          ((? string?)
+           (updated-url source-url))
+          ((source-url ...)
+           (find updated-url source-url)))
+        #f)))
+
+(define (github-package? package)
+  "Return true if PACKAGE is a package from GitHub, else false."
+  (not (eq? #f (updated-github-url package "dummy"))))
+
+(define (github-repository url)
+  "Return a string e.g. bedtools2 of the name of the repository, from a string
+URL of the form 'https://github.com/arq5x/bedtools2/archive/v2.24.0.tar.gz'"
+  (match (string-split (uri-path (string->uri url)) #\/)
+    ((_ owner project . rest)
+     (string-append project))))
+
+(define (github-user-slash-repository url)
+  "Return a string e.g. arq5x/bedtools2 of the owner and the name of the
+repository separated by a forward slash, from a string URL of the form
+'https://github.com/arq5x/bedtools2/archive/v2.24.0.tar.gz'"
+  (match (string-split (uri-path (string->uri url)) #\/)
+    ((_ owner project . rest)
+     (string-append owner "/" project))))
+
+(define %github-token
+  ;; Token to be passed to Github.com to avoid the 60-request per hour
+  ;; limit, or #f.
+  (make-parameter (getenv "GUIX_GITHUB_TOKEN")))
+
+(define (latest-released-version url package-name)
+  "Return a string of the newest released version name given a string URL like
+'https://github.com/arq5x/bedtools2/archive/v2.24.0.tar.gz' and the name of
+the package e.g. 'bedtools2'.  Return #f if there is no releases"
+  (let* ((token (%github-token))
+         (api-url (string-append
+                   "https://api.github.com/repos/"
+                   (github-user-slash-repository url)
+                   "/releases"))
+         (json (json-fetch*
+                (if token
+                    (string-append api-url "?access_token=" token)
+                    api-url))))
+    (if (eq? json #f)
+        (if token
+            (error "Error downloading release information through the GitHub
+API when using a GitHub token")
+            (error "Error downloading release information through the GitHub
+API. This may be fixed by using an access token and setting the environment
+variable GUIX_GITHUB_TOKEN, for instance one procured from
+https://github.com/settings/tokens"))
+        (let ((proper-releases
+               (filter
+                (lambda (x)
+                  ;; example pre-release:
+                  ;; https://github.com/wwood/OrfM/releases/tag/v0.5.1
+                  ;; or an all-prerelease set
+                  ;; https://github.com/powertab/powertabeditor/releases
+                  (not (hash-ref x "prerelease")))
+                json)))
+          (match proper-releases
+            (()                       ;empty release list
+             #f)
+            ((release . rest)         ;one or more releases
+             (let ((tag (hash-ref release "tag_name"))
+                   (name-length (string-length package-name)))
+               ;; some tags include the name of the package e.g. "fdupes-1.51"
+               ;; so remove these
+               (if (and (< name-length (string-length tag))
+                        (string=? (string-append package-name "-")
+                                  (substring tag 0 (+ name-length 1))))
+                   (substring tag (+ name-length 1))
+                   ;; some tags start with a "v" e.g. "v0.25.0"
+                   ;; where some are just the version number
+                   (if (eq? (string-ref tag 0) #\v)
+                       (substring tag 1) tag)))))))))
+
+(define (latest-release guix-package)
+  "Return an <upstream-source> for the latest release of GUIX-PACKAGE."
+  (let* ((pkg (specification->package guix-package))
+         (source-uri (origin-uri (package-source pkg)))
+         (name (package-name pkg))
+         (newest-version (latest-released-version source-uri name)))
+    (if newest-version
+        (upstream-source
+         (package pkg)
+         (version newest-version)
+         (urls (list (updated-github-url pkg newest-version))))
+        #f))) ; On GitHub but no proper releases
+
+(define %github-updater
+  (upstream-updater
+   (name 'github)
+   (description "Updater for GitHub packages")
+   (pred github-package?)
+   (latest latest-release)))
+
+
diff --git a/guix/licenses.scm b/guix/licenses.scm
index a43ab438f1..61e679358a 100644
--- a/guix/licenses.scm
+++ b/guix/licenses.scm
@@ -7,6 +7,7 @@
 ;;; Copyright © 2016 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2016 Leo Famulari <leo@famulari.name>
 ;;; Copyright © 2016 Fabian Harfert <fhmgufs@web.de>
+;;; Copyright © 2016 Rene Saavedra <rennes@openmailbox.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -33,7 +34,7 @@
             non-copyleft
             bsd-style                             ;deprecated!
             cc0
-            cc-by-sa4.0 cc-by-sa3.0 cc-by3.0
+            cc-by2.0 cc-by3.0 cc-by-sa2.0 cc-by-sa3.0 cc-by-sa4.0
             cddl1.0
             cecill-c
             artistic2.0 clarified-artistic
@@ -59,10 +60,12 @@
             openldap2.8 openssl
             psfl public-domain
             qpl
+            repoze
             ruby
             sgifreeb2.0
             silofl1.1
             sleepycat
+            tcl/tk
             unlicense
             vim
             x11 x11-style
@@ -154,11 +157,21 @@ at URI, which may be a file:// URI pointing the package's tree."
            "http://creativecommons.org/licenses/by-sa/3.0/"
            "Creative Commons Attribution-ShareAlike 3.0 Unported"))
 
+(define cc-by-sa2.0
+  (license "CC-BY-SA 2.0"
+           "http://creativecommons.org/licenses/by-sa/2.0/"
+           "Creative Commons Attribution-ShareAlike 2.0 Generic"))
+
 (define cc-by3.0
   (license "CC-BY 3.0"
            "http://creativecommons.org/licenses/by/3.0/"
            "Creative Commons Attribution 3.0 Unported"))
 
+(define cc-by2.0
+  (license "CC-BY 2.0"
+           "http://creativecommons.org/licenses/by/2.0/"
+           "Creative Commons Attribution 2.0 Generic"))
+
 (define cddl1.0
   (license "CDDL 1.0"
            "http://directory.fsf.org/wiki/License:CDDLv1.0"
@@ -368,6 +381,12 @@ at URI, which may be a file:// URI pointing the package's tree."
            "http://directory.fsf.org/wiki/License:QPLv1.0"
            "http://www.gnu.org/licenses/license-list.html#QPL"))
 
+(define repoze
+  (license "Repoze"
+           "http://repoze.org/LICENSE.txt"
+           "A BSD-like license with a clause requiring all changes to be
+           attributed by author and date."))
+
 (define ruby
   (license "Ruby License"
            "http://directory.fsf.org/wiki/License:Ruby"
@@ -388,6 +407,11 @@ at URI, which may be a file:// URI pointing the package's tree."
            "http://directory.fsf.org/wiki/License:Sleepycat"
            "https://www.gnu.org/licenses/license-list#BerkeleyDB"))
 
+(define tcl/tk
+  (license "Tcl/Tk"
+           "http://www.tcl.tk/software/tcltk/license.html"
+           "A non-copyleft free software license from the Tcl/Tk project"))
+
 (define vim
   (license "Vim"
            "http://directory.fsf.org/wiki/License:Vim7.2"
diff --git a/guix/packages.scm b/guix/packages.scm
index 6ec168c204..f6afaeb510 100644
--- a/guix/packages.scm
+++ b/guix/packages.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 © 2014, 2015 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2015 Eric Bavier <bavier@member.fsf.org>
 ;;;
@@ -25,6 +25,7 @@
   #:use-module (guix monads)
   #:use-module (guix gexp)
   #:use-module (guix base32)
+  #:use-module (guix grafts)
   #:use-module (guix derivations)
   #:use-module (guix build-system)
   #:use-module (guix search-paths)
@@ -984,7 +985,7 @@ This is an internal procedure."
                   (grafts
                    (let ((guile (package-derivation store (default-guile)
                                                     system #:graft? #f)))
-                     (graft-derivation store (bag-name bag) drv grafts
+                     (graft-derivation store drv grafts
                                        #:system system
                                        #:guile guile))))
                 drv))))
@@ -1002,7 +1003,7 @@ system identifying string)."
                   (()
                    drv)
                   (grafts
-                   (graft-derivation store (bag-name bag) drv grafts
+                   (graft-derivation store drv grafts
                                      #:system system
                                      #:guile
                                      (package-derivation store (default-guile)
diff --git a/guix/profiles.scm b/guix/profiles.scm
index ce86ff8e0a..1c53c8047a 100644
--- a/guix/profiles.scm
+++ b/guix/profiles.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 © 2013 Nikita Karetnikov <nikita@karetnikov.org>
 ;;; Copyright © 2014 Alex Kost <alezost@gmail.com>
 ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
@@ -694,11 +694,15 @@ creates the GTK+ 'icon-theme.cache' file for each theme."
 
 (define* (profile-derivation manifest
                              #:key
-                             (hooks %default-profile-hooks))
+                             (hooks %default-profile-hooks)
+                             system)
   "Return a derivation that builds a profile (aka. 'user environment') with
 the given MANIFEST.  The profile includes additional derivations returned by
 the monadic procedures listed in HOOKS--such as an Info 'dir' file, etc."
-  (mlet %store-monad ((extras (if (null? (manifest-entries manifest))
+  (mlet %store-monad ((system (if system
+                                  (return system)
+                                  (current-system)))
+                      (extras (if (null? (manifest-entries manifest))
                                   (return '())
                                   (sequence %store-monad
                                             (map (lambda (hook)
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index aa9c105f58..8725ddad88 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -23,6 +23,7 @@
   #:use-module (guix store)
   #:use-module (guix derivations)
   #:use-module (guix packages)
+  #:use-module (guix grafts)
   #:use-module (guix utils)
   #:use-module (guix monads)
   #:use-module (guix gexp)
diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm
index 2cc5f366a7..0e462de4bf 100644
--- a/guix/scripts/environment.scm
+++ b/guix/scripts/environment.scm
@@ -35,6 +35,9 @@
   #:use-module (gnu system file-systems)
   #:use-module (gnu packages)
   #:use-module (gnu packages bash)
+  #:use-module (gnu packages commencement)
+  #:use-module (gnu packages guile)
+  #:use-module ((gnu packages bootstrap) #:select (%bootstrap-guile))
   #:use-module (ice-9 format)
   #:use-module (ice-9 match)
   #:use-module (ice-9 rdelim)
@@ -45,19 +48,10 @@
   #:use-module (srfi srfi-98)
   #:export (guix-environment))
 
-(define (evaluate-input-search-paths inputs search-paths)
+(define (evaluate-profile-search-paths profile search-paths)
   "Evaluate SEARCH-PATHS, a list of search-path specifications, for the
-directories corresponding to INPUTS, a list of (DERIVATION) or (DERIVATION
-OUTPUT) tuples."
-  (let ((directories (map (match-lambda
-                            (((? derivation? drv))
-                             (derivation->output-path drv))
-                            (((? derivation? drv) output)
-                             (derivation->output-path drv output))
-                            (((? string? item))
-                             item))
-                          inputs)))
-    (evaluate-search-paths search-paths directories)))
+directories in PROFILE, the store path of a profile."
+  (evaluate-search-paths search-paths (list profile)))
 
 ;; Protect some env vars from purification.  Borrowed from nix-shell.
 (define %precious-variables
@@ -81,11 +75,10 @@ as 'HOME' and 'USER' are left untouched."
                       (((names . _) ...)
                        names)))))
 
-(define (create-environment inputs paths pure?)
-  "Set the environment variables specified by PATHS for all the packages
-within INPUTS.  When PURE? is #t, unset the variables in the current
-environment.  Otherwise, augment existing enviroment variables with additional
-search paths."
+(define (create-environment profile paths pure?)
+  "Set the environment variables specified by PATHS for PROFILE.  When PURE?
+is #t, unset the variables in the current environment.  Otherwise, augment
+existing enviroment variables with additional search paths."
   (when pure? (purify-environment))
   (for-each (match-lambda
               ((($ <search-path-specification> variable _ separator) . value)
@@ -94,15 +87,14 @@ search paths."
                          (if (and current (not pure?))
                              (string-append value separator current)
                              value)))))
-            (evaluate-input-search-paths inputs paths))
+            (evaluate-profile-search-paths profile paths))
 
   ;; Give users a way to know that they're in 'guix environment', so they can
   ;; adjust 'PS1' accordingly, for instance.
   (setenv "GUIX_ENVIRONMENT" "t"))
 
-(define (show-search-paths inputs search-paths pure?)
-  "Display SEARCH-PATHS applied to the packages specified by INPUTS, a list of
- (DERIVATION) or (DERIVATION OUTPUT) tuples.  When PURE? is #t, do not augment
+(define (show-search-paths profile search-paths pure?)
+  "Display SEARCH-PATHS applied to PROFILE.  When PURE? is #t, do not augment
 existing environment variables with additional search paths."
   (for-each (match-lambda
               ((search-path . value)
@@ -110,12 +102,37 @@ existing environment variables with additional search paths."
                 (search-path-definition search-path value
                                         #:kind (if pure? 'exact 'prefix)))
                (newline)))
-            (evaluate-input-search-paths inputs search-paths)))
+            (evaluate-profile-search-paths profile search-paths)))
+
+(define (strip-input-name input)
+  "Remove the name element from the tuple INPUT."
+  (match input
+    ((_ package) package)
+    ((_ package output)
+     (list package output))))
 
 (define (package+propagated-inputs package output)
   "Return the union of PACKAGE's OUTPUT and its transitive propagated inputs."
-  `((,(package-name package) ,package ,output)
-    ,@(package-transitive-propagated-inputs package)))
+  (cons (list package output)
+        (map strip-input-name
+             (package-transitive-propagated-inputs package))))
+
+(define (package-or-package+output? expr)
+  "Return #t if EXPR is a package or a 2 element list consisting of a package
+and an output string."
+  (match expr
+    ((or (? package?) ; bare package object
+         ((? package?) (? string?))) ; package+output tuple
+     #t)
+    (_ #f)))
+
+(define (package-environment-inputs package)
+  "Return a list of the transitive input packages for PACKAGE."
+  ;; Remove non-package inputs such as origin records.
+  (filter package-or-package+output?
+          (map strip-input-name
+               (bag-transitive-inputs
+                (package->bag package)))))
 
 (define (show-help)
   (display (_ "Usage: guix environment [OPTION]... PACKAGE... [-- COMMAND...]
@@ -252,17 +269,19 @@ COMMAND or an interactive shell in that environment.\n"))
 (define (options/resolve-packages opts)
   "Return OPTS with package specification strings replaced by actual
 packages."
-  (define (package->outputs package mode)
-    (map (lambda (output)
-           (list mode package output))
-         (package-outputs package)))
+  (define (package->output package mode)
+    (match package
+      ((? package?)
+       (list mode package "out"))
+      (((? package? package) (? string? output))
+       (list mode package output))))
 
   (define (packages->outputs packages mode)
     (match packages
-      ((? package? package)
-       (package->outputs package mode))
-      (((? package? packages) ...)
-       (append-map (cut package->outputs <> mode) packages))))
+      ((? package-or-package+output? package) ; single package
+       (list (package->output package mode)))
+      (((? package-or-package+output?) ...) ; many packages
+       (map (cut package->output <> mode) packages))))
 
   (compact
    (append-map (match-lambda
@@ -280,22 +299,30 @@ packages."
                  (_ '(#f)))
                opts)))
 
-(define (build-inputs inputs opts)
-  "Build the derivations in INPUTS, a list of (DERIVATION) or (DERIVATION
-OUTPUT) tuples, using the build options in OPTS."
+(define* (build-environment derivations opts)
+  "Build the DERIVATIONS required by the environment using the build options
+in OPTS."
   (let ((substitutes? (assoc-ref opts 'substitutes?))
         (dry-run?     (assoc-ref opts 'dry-run?)))
-    (match inputs
-      (((derivations _ ...) ...)
-       (mbegin %store-monad
-         (show-what-to-build* derivations
-                              #:use-substitutes? substitutes?
-                              #:dry-run? dry-run?)
-         (if dry-run?
-             (return #f)
-             (mbegin %store-monad
-               (built-derivations derivations)
-               (return derivations))))))))
+    (mbegin %store-monad
+      (show-what-to-build* derivations
+                           #:use-substitutes? substitutes?
+                           #:dry-run? dry-run?)
+      (if dry-run?
+          (return #f)
+          (mbegin %store-monad
+            (set-build-options-from-command-line* opts)
+            (built-derivations derivations))))))
+
+(define (inputs->profile-derivation inputs system bootstrap?)
+  "Return the derivation for a profile consisting of INPUTS for SYSTEM.
+BOOTSTRAP?  specifies whether to use the bootstrap Guile to build the
+profile."
+  (profile-derivation (packages->manifest inputs)
+                      #:system system
+                      #:hooks (if bootstrap?
+                                  '()
+                                  %default-profile-hooks)))
 
 (define requisites* (store-lift requisites))
 
@@ -334,16 +361,15 @@ variables are cleared before setting the new ones."
   (apply system* command))
 
 (define* (launch-environment/container #:key command bash user-mappings
-                                       inputs paths network?)
-  "Run COMMAND within a Linux container.  The environment features INPUTS, a
-list of derivations to be shared from the host system.  Environment variables
-are set according to PATHS, a list of native search paths.  The global shell
-is BASH, a file name for a GNU Bash binary in the store.  When NETWORK?,
-access to the host system network is permitted.  USER-MAPPINGS, a list of file
-system mappings, contains the user-specified host file systems to mount inside
-the container."
+                                       profile paths network?)
+  "Run COMMAND within a container that features the software in PROFILE.
+Environment variables are set according to PATHS, a list of native search
+paths.  The global shell is BASH, a file name for a GNU Bash binary in the
+store.  When NETWORK?, access to the host system network is permitted.
+USER-MAPPINGS, a list of file system mappings, contains the user-specified
+host file systems to mount inside the container."
   (mlet %store-monad ((reqs (inputs->requisites
-                             (cons (direct-store-path bash) inputs))))
+                             (list (direct-store-path bash) profile))))
     (return
      (let* ((cwd (getcwd))
             ;; Bind-mount all requisite store items, user-specified mappings,
@@ -408,7 +434,7 @@ the container."
             (primitive-exit/status
              ;; A container's environment is already purified, so no need to
              ;; request it be purified again.
-             (launch-environment command inputs paths #f)))
+             (launch-environment command profile paths #f)))
           #:namespaces (if network?
                            (delq 'net %namespaces) ; share host network
                            %namespaces)))))))
@@ -482,64 +508,65 @@ message if any test fails."
                                       (('ad-hoc-package package output)
                                        (package+propagated-inputs package
                                                                   output))
-                                      (('package package output)
-                                       (bag-transitive-inputs
-                                        (package->bag package))))
+                                      (('package package _)
+                                       (package-environment-inputs package)))
                                     packages)))
            (paths      (delete-duplicates
                         (cons $PATH
                               (append-map (match-lambda
-                                           ((label (? package? p) _ ...)
-                                            (package-native-search-paths p))
-                                           (_
-                                            '()))
+                                            ((or ((? package? p) _ ...)
+                                                 (? package? p))
+                                             (package-native-search-paths p))
+                                            (_ '()))
                                           inputs))
                         eq?)))
 
       (when container? (assert-container-features))
 
       (with-store store
-        (set-build-options-from-command-line store opts)
-        (run-with-store store
-          (mlet* %store-monad ((inputs (lower-inputs
-                                        (map (match-lambda
-                                              ((label item)
-                                               (list item))
-                                              ((label item output)
-                                               (list item output)))
-                                             inputs)
-                                        #:system system))
-                               ;; Containers need a Bourne shell at /bin/sh.
-                               (bash (environment-bash container?
-                                                       bootstrap?
-                                                       system)))
-            (mbegin %store-monad
+        ;; Use the bootstrap Guile when requested.
+        (parameterize ((%guile-for-build
+                        (package-derivation
+                         store
+                         (if bootstrap?
+                             %bootstrap-guile
+                             (canonical-package guile-2.0)))))
+          (set-build-options-from-command-line store opts)
+          (run-with-store store
+            ;; Containers need a Bourne shell at /bin/sh.
+            (mlet* %store-monad ((bash       (environment-bash container?
+                                                               bootstrap?
+                                                               system))
+                                 (prof-drv   (inputs->profile-derivation
+                                              inputs system bootstrap?))
+                                 (profile -> (derivation->output-path prof-drv)))
               ;; First build the inputs.  This is necessary even for
-              ;; --search-paths.  Additionally, we might need to build bash
-              ;; for a container.
-              (build-inputs (if (derivation? bash)
-                                `((,bash "out") ,@inputs)
-                                inputs)
-                            opts)
-              (cond
-               ((assoc-ref opts 'dry-run?)
-                (return #t))
-               ((assoc-ref opts 'search-paths)
-                (show-search-paths inputs paths pure?)
-                (return #t))
-               (container?
-                (let ((bash-binary
-                       (if bootstrap?
-                           bash
-                           (string-append (derivation->output-path bash)
-                                          "/bin/sh"))))
-                  (launch-environment/container #:command command
-                                                #:bash bash-binary
-                                                #:user-mappings mappings
-                                                #:inputs inputs
-                                                #:paths paths
-                                                #:network? network?)))
-               (else
-                (return
-                 (exit/status
-                  (launch-environment command inputs paths pure?))))))))))))
+              ;; --search-paths.  Additionally, we might need to build bash for
+              ;; a container.
+              (mbegin %store-monad
+                (build-environment (if (derivation? bash)
+                                       (list prof-drv bash)
+                                       (list prof-drv))
+                                   opts)
+                (cond
+                 ((assoc-ref opts 'dry-run?)
+                  (return #t))
+                 ((assoc-ref opts 'search-paths)
+                  (show-search-paths profile paths pure?)
+                  (return #t))
+                 (container?
+                  (let ((bash-binary
+                         (if bootstrap?
+                             bash
+                             (string-append (derivation->output-path bash)
+                                            "/bin/sh"))))
+                    (launch-environment/container #:command command
+                                                  #:bash bash-binary
+                                                  #:user-mappings mappings
+                                                  #:profile profile
+                                                  #:paths paths
+                                                  #:network? network?)))
+                 (else
+                  (return
+                   (exit/status
+                    (launch-environment command profile paths pure?)))))))))))))
diff --git a/guix/scripts/package.scm b/guix/scripts/package.scm
index b93ffb0b6b..f65834386b 100644
--- a/guix/scripts/package.scm
+++ b/guix/scripts/package.scm
@@ -2,7 +2,7 @@
 ;;; Copyright © 2012, 2013, 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
 ;;; Copyright © 2013, 2015 Mark H Weaver <mhw@netris.org>
-;;; Copyright © 2014 Alex Kost <alezost@gmail.com>
+;;; Copyright © 2014, 2016 Alex Kost <alezost@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -551,10 +551,6 @@ upgrading, #f otherwise."
 (define (options->installable opts manifest)
   "Given MANIFEST, the current manifest, and OPTS, the result of 'args-fold',
 return the new list of manifest entries."
-  (define (package->manifest-entry* package output)
-    (check-package-freshness package)
-    (package->manifest-entry package output))
-
   (define upgrade?
     (options->upgrade-predicate opts))
 
@@ -567,7 +563,7 @@ return the new list of manifest entries."
                           (call-with-values
                               (lambda ()
                                 (specification->package+output name output))
-                            package->manifest-entry*))))
+                            package->manifest-entry))))
                   (_ #f))
                 (manifest-entries manifest)))
 
@@ -576,13 +572,13 @@ return the new list of manifest entries."
                   (('install . (? package? p))
                    ;; When given a package via `-e', install the first of its
                    ;; outputs (XXX).
-                   (package->manifest-entry* p "out"))
+                   (package->manifest-entry p "out"))
                   (('install . (? string? spec))
                    (if (store-path? spec)
                        (store-item->manifest-entry spec)
                        (let-values (((package output)
                                      (specification->package+output spec)))
-                         (package->manifest-entry* package output))))
+                         (package->manifest-entry package output))))
                   (_ #f))
                 opts))
 
diff --git a/guix/scripts/publish.scm b/guix/scripts/publish.scm
index fb7b4218e0..46292131d7 100644
--- a/guix/scripts/publish.scm
+++ b/guix/scripts/publish.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 David Thompson <davet@gnu.org>
-;;; Copyright © 2015 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -142,10 +142,11 @@ Publish ~a over HTTP.\n") %store-directory)
 (define base64-encode-string
   (compose base64-encode string->utf8))
 
-(define (narinfo-string store-path path-info key)
-  "Generate a narinfo key/value string for STORE-PATH using the details in
-PATH-INFO.  The narinfo is signed with KEY."
-  (let* ((url        (string-append "nar/" (basename store-path)))
+(define (narinfo-string store store-path key)
+  "Generate a narinfo key/value string for STORE-PATH; an exception is raised
+if STORE-PATH is invalid.  The narinfo is signed with KEY."
+  (let* ((path-info  (query-path-info store store-path))
+         (url        (string-append "nar/" (basename store-path)))
          (hash       (bytevector->nix-base32-string
                       (path-info-hash path-info)))
          (size       (path-info-nar-size path-info))
@@ -163,7 +164,7 @@ References: ~a~%"
                              store-path url hash size references))
          ;; Do not render a "Deriver" or "System" line if we are rendering
          ;; info for a derivation.
-         (info       (if (string-null? deriver)
+         (info       (if (not deriver)
                          base-info
                          (catch 'system-error
                            (lambda ()
@@ -199,23 +200,21 @@ References: ~a~%"
 
 (define (render-narinfo store request hash)
   "Render metadata for the store path corresponding to HASH."
-  (let* ((store-path (hash-part->path store hash))
-         (path-info (and (not (string-null? store-path))
-                         (query-path-info store store-path))))
-    (if path-info
+  (let ((store-path (hash-part->path store hash)))
+    (if (string-null? store-path)
+        (not-found request)
         (values '((content-type . (application/x-nix-narinfo)))
                 (cut display
-                     (narinfo-string store-path path-info (force %private-key))
-                     <>))
-        (not-found request))))
+                     (narinfo-string store store-path (force %private-key))
+                     <>)))))
 
-(define (render-nar request store-item)
+(define (render-nar store request store-item)
   "Render archive of the store path corresponding to STORE-ITEM."
   (let ((store-path (string-append %store-directory "/" store-item)))
     ;; The ISO-8859-1 charset *must* be used otherwise HTTP clients will
     ;; interpret the byte stream as UTF-8 and arbitrarily change invalid byte
     ;; sequences.
-    (if (file-exists? store-path)
+    (if (valid-path? store store-path)
         (values '((content-type . (application/x-nix-archive
                                    (charset . "ISO-8859-1"))))
                 ;; XXX: We're not returning the actual contents, deferring
@@ -315,7 +314,7 @@ blocking."
            (render-narinfo store request hash))
           ;; /nar/<store-item>
           (("nar" store-item)
-           (render-nar request store-item))
+           (render-nar store request store-item))
           (_ (not-found request)))
         (not-found request))))
 
diff --git a/guix/scripts/refresh.scm b/guix/scripts/refresh.scm
index f9e3f31a03..e541138682 100644
--- a/guix/scripts/refresh.scm
+++ b/guix/scripts/refresh.scm
@@ -1,8 +1,9 @@
 ;;; 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 © 2013 Nikita Karetnikov <nikita@karetnikov.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
 ;;; Copyright © 2015 Alex Kost <alezost@gmail.com>
+;;; Copyright © 2016 Ben Woodcroft <donttrustben@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -31,7 +32,7 @@
   #:use-module (guix scripts graph)
   #:use-module (guix monads)
   #:use-module ((guix gnu-maintenance)
-                #:select (%gnu-updater %gnome-updater))
+                #:select (%gnu-updater %gnome-updater %xorg-updater))
   #:use-module (guix import elpa)
   #:use-module (guix import cran)
   #:use-module (guix gnupg)
@@ -193,10 +194,13 @@ unavailable optional dependencies such as Guile-JSON."
   ;; List of "updaters" used by default.  They are consulted in this order.
   (list-updaters %gnu-updater
                  %gnome-updater
+                 %xorg-updater
                  %elpa-updater
                  %cran-updater
                  %bioconductor-updater
-                 ((guix import pypi) => %pypi-updater)))
+                 ((guix import pypi) => %pypi-updater)
+                 ((guix import gem) => %gem-updater)
+                 ((guix import github) => %github-updater)))
 
 (define (lookup-updater name)
   "Return the updater called NAME."
diff --git a/guix/scripts/system.scm b/guix/scripts/system.scm
index 7279be0c43..401aa8b60a 100644
--- a/guix/scripts/system.scm
+++ b/guix/scripts/system.scm
@@ -211,6 +211,19 @@ the ownership of '~a' may be incorrect!~%")
       (lambda ()
         (environ env)))))
 
+(define-syntax-rule (save-load-path-excursion body ...)
+  "Save the current values of '%load-path' and '%load-compiled-path', run
+BODY..., and restore them."
+  (let ((path %load-path)
+        (cpath %load-compiled-path))
+    (dynamic-wind
+      (const #t)
+      (lambda ()
+        body ...)
+      (lambda ()
+        (set! %load-path path)
+        (set! %load-compiled-path cpath)))))
+
 (define-syntax-rule (warn-on-system-error body ...)
   (catch 'system-error
     (lambda ()
@@ -273,6 +286,9 @@ bring the system down."
            (info (_ "loading new services:~{ ~a~}...~%") to-load-names)
            (mlet %store-monad ((files (mapm %store-monad shepherd-service-file
                                             to-load)))
+             ;; Here we assume that FILES are exactly those that were computed
+             ;; as part of the derivation that built OS, which is normally the
+             ;; case.
              (load-services (map derivation->output-path files))
 
              (for-each start-service
@@ -299,7 +315,12 @@ it atomically, and then run OS's activation script."
        ;; Tell 'activate-current-system' what the new system is.
        (setenv "GUIX_NEW_SYSTEM" system)
 
-       (primitive-load (derivation->output-path script)))
+       ;; The activation script may modify '%load-path' & co., so protect
+       ;; against that.  This is necessary to ensure that
+       ;; 'upgrade-shepherd-services' gets to see the right modules when it
+       ;; computes derivations with (gexp->derivation #:modules …).
+       (save-load-path-excursion
+        (primitive-load (derivation->output-path script))))
 
       ;; Finally, try to update system services.
       (upgrade-shepherd-services os))))
diff --git a/guix/store.scm b/guix/store.scm
index 3c4d1c0058..8746d3c2d6 100644
--- a/guix/store.scm
+++ b/guix/store.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.
 ;;;
@@ -118,6 +118,8 @@
             store-lower
             run-with-store
             %guile-for-build
+            current-system
+            set-current-system
             text-file
             interned-file
 
@@ -240,14 +242,16 @@
 (define-record-type <path-info>
   (path-info deriver hash references registration-time nar-size)
   path-info?
-  (deriver path-info-deriver)
+  (deriver path-info-deriver)                     ;string | #f
   (hash path-info-hash)
   (references path-info-references)
   (registration-time path-info-registration-time)
   (nar-size path-info-nar-size))
 
 (define (read-path-info p)
-  (let ((deriver  (read-store-path p))
+  (let ((deriver  (match (read-store-path p)
+                    ("" #f)
+                    (x  x)))
         (hash     (base16-string->bytevector (read-string p)))
         (refs     (read-store-path-list p))
         (registration-time (read-int p))
@@ -580,7 +584,12 @@ encoding conversion errors."
     (operation (name args ...) docstring return ...)))
 
 (define-operation (valid-path? (string path))
-  "Return #t when PATH is a valid store path."
+  "Return #t when PATH designates a valid store item and #f otherwise (an
+invalid item may exist on disk but still be invalid, for instance because it
+is the result of an aborted or failed build.)
+
+A '&nix-protocol-error' condition is raised if PATH is not prefixed by the
+store directory (/gnu/store)."
   boolean)
 
 (define-operation (query-path-hash (store-path path))
@@ -1040,6 +1049,18 @@ permission bits are kept."
 (define set-build-options*
   (store-lift set-build-options))
 
+(define-inlinable (current-system)
+  ;; Consult the %CURRENT-SYSTEM fluid at bind time.  This is equivalent to
+  ;; (lift0 %current-system %store-monad), but inlinable, thus avoiding
+  ;; closure allocation in some cases.
+  (lambda (state)
+    (values (%current-system) state)))
+
+(define-inlinable (set-current-system system)
+  ;; Set the %CURRENT-SYSTEM fluid at bind time.
+  (lambda (state)
+    (values (%current-system system) state)))
+
 (define %guile-for-build
   ;; The derivation of the Guile to be used within the build environment,
   ;; when using 'gexp->derivation' and co.
diff --git a/tests/derivations.scm b/tests/derivations.scm
index db96e26ab1..9b53019cc5 100644
--- a/tests/derivations.scm
+++ b/tests/derivations.scm
@@ -929,40 +929,6 @@
                                     ((p2 . _)
                                      (string<? p1 p2)))))))))))))
 
-
-(test-assert "graft-derivation"
-  (let* ((build `(begin
-                   (mkdir %output)
-                   (chdir %output)
-                   (symlink %output "self")
-                   (call-with-output-file "text"
-                     (lambda (output)
-                       (format output "foo/~a/bar" ,%mkdir)))
-                   (symlink ,%bash "sh")))
-         (orig  (build-expression->derivation %store "graft" build
-                                              #:inputs `(("a" ,%bash)
-                                                         ("b" ,%mkdir))))
-         (one   (add-text-to-store %store "bash" "fake bash"))
-         (two   (build-expression->derivation %store "mkdir"
-                                              '(call-with-output-file %output
-                                                 (lambda (port)
-                                                   (display "fake mkdir" port)))))
-         (graft (graft-derivation %store "graft" orig
-                                  (list (graft
-                                          (origin %bash)
-                                          (replacement one))
-                                        (graft
-                                          (origin %mkdir)
-                                          (replacement two))))))
-    (and (build-derivations %store (list graft))
-         (let ((two   (derivation->output-path two))
-               (graft (derivation->output-path graft)))
-           (and (string=? (format #f "foo/~a/bar" two)
-                          (call-with-input-file (string-append graft "/text")
-                            get-string-all))
-                (string=? (readlink (string-append graft "/sh")) one)
-                (string=? (readlink (string-append graft "/self")) graft))))))
-
 (test-equal "map-derivation"
   "hello"
   (let* ((joke (package-derivation %store guile-1.8))
diff --git a/tests/grafts.scm b/tests/grafts.scm
new file mode 100644
index 0000000000..4a4122a3e9
--- /dev/null
+++ b/tests/grafts.scm
@@ -0,0 +1,81 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2014, 2015, 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 (test-grafts)
+  #:use-module (guix derivations)
+  #:use-module (guix store)
+  #:use-module (guix utils)
+  #:use-module (guix grafts)
+  #:use-module (guix tests)
+  #:use-module ((gnu packages) #:select (search-bootstrap-binary))
+  #:use-module (srfi srfi-64)
+  #:use-module (rnrs io ports))
+
+(define %store
+  (open-connection-for-tests))
+
+(define (bootstrap-binary name)
+  (let ((bin (search-bootstrap-binary name (%current-system))))
+    (and %store
+         (add-to-store %store name #t "sha256" bin))))
+
+(define %bash
+  (bootstrap-binary "bash"))
+(define %mkdir
+  (bootstrap-binary "mkdir"))
+
+
+(test-begin "grafts")
+
+(test-assert "graft-derivation"
+  (let* ((build `(begin
+                   (mkdir %output)
+                   (chdir %output)
+                   (symlink %output "self")
+                   (call-with-output-file "text"
+                     (lambda (output)
+                       (format output "foo/~a/bar" ,%mkdir)))
+                   (symlink ,%bash "sh")))
+         (orig  (build-expression->derivation %store "graft" build
+                                              #:inputs `(("a" ,%bash)
+                                                         ("b" ,%mkdir))))
+         (one   (add-text-to-store %store "bash" "fake bash"))
+         (two   (build-expression->derivation %store "mkdir"
+                                              '(call-with-output-file %output
+                                                 (lambda (port)
+                                                   (display "fake mkdir" port)))))
+         (graft (graft-derivation %store orig
+                                  (list (graft
+                                          (origin %bash)
+                                          (replacement one))
+                                        (graft
+                                          (origin %mkdir)
+                                          (replacement two))))))
+    (and (build-derivations %store (list graft))
+         (let ((two   (derivation->output-path two))
+               (graft (derivation->output-path graft)))
+           (and (string=? (format #f "foo/~a/bar" two)
+                          (call-with-input-file (string-append graft "/text")
+                            get-string-all))
+                (string=? (readlink (string-append graft "/sh")) one)
+                (string=? (readlink (string-append graft "/self")) graft))))))
+
+(test-end)
+
+
+(exit (= (test-runner-fail-count (test-runner-current)) 0))
diff --git a/tests/guix-environment-container.sh b/tests/guix-environment-container.sh
index 703ab31d27..aba34a3bd0 100644
--- a/tests/guix-environment-container.sh
+++ b/tests/guix-environment-container.sh
@@ -73,7 +73,7 @@ guix environment --container --ad-hoc --bootstrap guile-bootstrap \
      -- guile -c "$mount_test_code" > $tmpdir/mounts
 
 cat "$tmpdir/mounts"
-test `wc -l < $tmpdir/mounts` -eq 3
+test `wc -l < $tmpdir/mounts` -eq 4
 
 current_dir="`cd $PWD; pwd -P`"
 grep -e "$current_dir$" $tmpdir/mounts # current directory
diff --git a/tests/guix-environment.sh b/tests/guix-environment.sh
index aed27c103c..5ad8dfa82a 100644
--- a/tests/guix-environment.sh
+++ b/tests/guix-environment.sh
@@ -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>
 #
 # This file is part of GNU Guix.
 #
@@ -34,17 +34,23 @@ mkdir "$tmpdir"
 export SHELL
 
 # Check the environment variables for the bootstrap Guile.
-guix environment --ad-hoc guile-bootstrap --pure --search-paths > "$tmpdir/a"
-guix environment --ad-hoc guile-bootstrap:out --pure --search-paths > "$tmpdir/b"
+guix environment --bootstrap --ad-hoc guile-bootstrap --pure \
+     --search-paths > "$tmpdir/a"
+guix environment --bootstrap --ad-hoc guile-bootstrap:out --pure \
+     --search-paths > "$tmpdir/b"
 
 # $PATH must appear in the search paths, and nothing else.
-grep -E '^export PATH=.*guile-bootstrap-[0-9.]+/bin' "$tmpdir/a"
+grep -E '^export PATH=.*profile/bin' "$tmpdir/a"
 test "`wc -l < "$tmpdir/a"`" = 1
 
+# Guile must be on $PATH.
+test -x `sed -r 's/^export PATH="(.*)"/\1/' "$tmpdir/a"`/guile
+
 cmp "$tmpdir/a" "$tmpdir/b"
 
 # Make sure the exit value is preserved.
-if guix environment --ad-hoc guile-bootstrap --pure -- guile -c '(exit 42)'
+if guix environment --bootstrap --ad-hoc guile-bootstrap --pure \
+        -- guile -c '(exit 42)'
 then
     false
 else
@@ -52,7 +58,8 @@ else
 fi
 
 # Same as above, but with deprecated -E flag.
-if guix environment --ad-hoc guile-bootstrap --pure -E "guile -c '(exit 42)'"
+if guix environment --bootstrap --ad-hoc guile-bootstrap --pure \
+        -E "guile -c '(exit 42)'"
 then
     false
 else
@@ -62,22 +69,29 @@ fi
 if guile -c '(getaddrinfo "www.gnu.org" "80" AI_NUMERICSERV)' 2> /dev/null
 then
     # Compute the build environment for the initial GNU Make.
-    guix environment -e '(@@ (gnu packages commencement) gnu-make-boot0)' \
-	 --no-substitutes --search-paths --pure > "$tmpdir/a"
+    guix environment --bootstrap --no-substitutes --search-paths --pure \
+         -e '(@@ (gnu packages commencement) gnu-make-boot0)' > "$tmpdir/a"
+
+    # Make sure bootstrap binaries are in the profile.
+    profile=`grep "^export PATH" "$tmpdir/a" | sed -r 's|^.*="(.*)/bin"|\1|'`
 
     # Make sure the bootstrap binaries are all listed where they belong.
-    grep -E '^export PATH=.*-bootstrap-binaries-0/bin'      "$tmpdir/a"
-    grep -E '^export CPATH=.*-gcc-bootstrap-0/include'      "$tmpdir/a"
-    grep -E '^export CPATH=.*-glibc-bootstrap-0/include'    "$tmpdir/a"
-    grep -E '^export LIBRARY_PATH=.*-glibc-bootstrap-0/lib' "$tmpdir/a"
+    grep -E "^export PATH=\"$profile/bin\""         "$tmpdir/a"
+    grep -E "^export CPATH=\"$profile/include\""    "$tmpdir/a"
+    grep -E "^export LIBRARY_PATH=\"$profile/lib\"" "$tmpdir/a"
+    for dep in bootstrap-binaries-0 gcc-bootstrap-0 glibc-bootstrap-0
+    do
+	guix gc --references "$profile" | grep "$dep"
+    done
 
     # 'make-boot0' itself must not be listed.
-    if grep "make-boot0" "$tmpdir/a"; then false; else true; fi
+    if guix gc --references "$profile" | grep make-boot0
+    then false; else true; fi
 
     # Make sure that the shell spawned with '--exec' sees the same environment
     # as returned by '--search-paths'.
-    guix environment -e '(@@ (gnu packages commencement) gnu-make-boot0)'	\
-	 --no-substitutes --pure						\
+    guix environment --bootstrap --no-substitutes --pure \
+         -e '(@@ (gnu packages commencement) gnu-make-boot0)' \
          -- /bin/sh -c 'echo $PATH $CPATH $LIBRARY_PATH' > "$tmpdir/b"
     ( . "$tmpdir/a" ; echo $PATH $CPATH $LIBRARY_PATH ) > "$tmpdir/c"
     cmp "$tmpdir/b" "$tmpdir/c"
@@ -85,45 +99,57 @@ then
     rm "$tmpdir"/*
 
     # Compute the build environment for the initial GNU Findutils.
-    guix environment -e '(@@ (gnu packages commencement) findutils-boot0)' \
-	 --no-substitutes --search-paths --pure > "$tmpdir/a"
+    guix environment --bootstrap --no-substitutes --search-paths --pure \
+         -e '(@@ (gnu packages commencement) findutils-boot0)' > "$tmpdir/a"
+    profile=`grep "^export PATH" "$tmpdir/a" | sed -r 's|^.*="(.*)/bin"|\1|'`
 
     # Make sure the bootstrap binaries are all listed where they belong.
-    grep -E '^export PATH=.*-bootstrap-binaries-0/bin'      "$tmpdir/a"
-    grep -E '^export PATH=.*-make-boot0-[0-9.]+/bin'        "$tmpdir/a"
-    grep -E '^export CPATH=.*-gcc-bootstrap-0/include'      "$tmpdir/a"
-    grep -E '^export CPATH=.*-glibc-bootstrap-0/include'    "$tmpdir/a"
-    grep -E '^export LIBRARY_PATH=.*-glibc-bootstrap-0/lib' "$tmpdir/a"
+    grep -E "^export PATH=\"$profile/bin\""         "$tmpdir/a"
+    grep -E "^export CPATH=\"$profile/include\""    "$tmpdir/a"
+    grep -E "^export LIBRARY_PATH=\"$profile/lib\"" "$tmpdir/a"
+    for dep in bootstrap-binaries-0 gcc-bootstrap-0 glibc-bootstrap-0 \
+				    make-boot0
+    do
+	guix gc --references "$profile" | grep "$dep"
+    done
 
     # The following test assumes 'make-boot0' has a "debug" output.
     make_boot0_debug="`guix build -e '(@@ (gnu packages commencement) gnu-make-boot0)' | grep -e -debug`"
     test "x$make_boot0_debug" != "x"
 
     # Make sure the "debug" output is not listed.
-    if grep -E "$make_boot0_debug" "$tmpdir/a"; then false; else true; fi
+    if guix gc --references "$profile" | grep "$make_boot0_debug"
+    then false; else true; fi
 
     # Compute the build environment for the initial GNU Make, but add in the
     # bootstrap Guile as an ad-hoc addition.
-    guix environment -e '(@@ (gnu packages commencement) gnu-make-boot0)' \
-         --ad-hoc guile-bootstrap --no-substitutes --search-paths \
-         --pure > "$tmpdir/a"
+    guix environment --bootstrap --no-substitutes --search-paths --pure	\
+         -e '(@@ (gnu packages commencement) gnu-make-boot0)'		\
+         --ad-hoc guile-bootstrap > "$tmpdir/a"
+    profile=`grep "^export PATH" "$tmpdir/a" | sed -r 's|^.*="(.*)/bin"|\1|'`
 
     # Make sure the bootstrap binaries are all listed where they belong.
-    cat $tmpdir/a
-    grep -E '^export PATH=.*-bootstrap-binaries-0/bin'      "$tmpdir/a"
-    grep -E '^export PATH=.*-guile-bootstrap-2.0/bin'       "$tmpdir/a"
-    grep -E '^export CPATH=.*-gcc-bootstrap-0/include'      "$tmpdir/a"
-    grep -E '^export CPATH=.*-glibc-bootstrap-0/include'    "$tmpdir/a"
-    grep -E '^export LIBRARY_PATH=.*-glibc-bootstrap-0/lib' "$tmpdir/a"
-
-    # Make sure a package list can be used with -e.
+    grep -E "^export PATH=\"$profile/bin\""         "$tmpdir/a"
+    grep -E "^export CPATH=\"$profile/include\""    "$tmpdir/a"
+    grep -E "^export LIBRARY_PATH=\"$profile/lib\"" "$tmpdir/a"
+    for dep in bootstrap-binaries-0 gcc-bootstrap-0 glibc-bootstrap-0 \
+				    guile-bootstrap
+    do
+	guix gc --references "$profile" | grep "$dep"
+    done
+
+    # Make sure a package list with plain package objects and package+output
+    # tuples can be used with -e.
     expr_list_test_code="
 (list (@@ (gnu packages commencement) gnu-make-boot0)
-      (@ (gnu packages bootstrap) %bootstrap-guile))"
+      (list (@ (gnu packages bootstrap) %bootstrap-guile) \"out\"))"
 
-    guix environment --ad-hoc --no-substitutes --search-paths --pure \
-         -e "$expr_list_test_code" > "$tmpdir/a"
+    guix environment --bootstrap --ad-hoc --no-substitutes --search-paths \
+         --pure -e "$expr_list_test_code" > "$tmpdir/a"
+    profile=`grep "^export PATH" "$tmpdir/a" | sed -r 's|^.*="(.*)/bin"|\1|'`
 
-    grep -E '^export PATH=.*-make-boot0-4.1/bin'      "$tmpdir/a"
-    grep -E '^export PATH=.*-guile-bootstrap-2.0/bin' "$tmpdir/a"
+    for dep in make-boot0 guile-bootstrap
+    do
+	guix gc --references "$profile" | grep "$dep"
+    done
 fi
diff --git a/tests/packages.scm b/tests/packages.scm
index 9d37fb68d6..6315c2204f 100644
--- a/tests/packages.scm
+++ b/tests/packages.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.
 ;;;
@@ -29,6 +29,7 @@
   #:use-module (guix hash)
   #:use-module (guix derivations)
   #:use-module (guix packages)
+  #:use-module (guix grafts)
   #:use-module (guix search-paths)
   #:use-module (guix build-system)
   #:use-module (guix build-system trivial)
@@ -615,7 +616,7 @@
          (guile (package-derivation %store (canonical-package guile-2.0)
                                     #:graft? #f)))
     (equal? (package-derivation %store dummy)
-            (graft-derivation %store "dummy-0"
+            (graft-derivation %store
                               (package-derivation %store dummy #:graft? #f)
                               (package-grafts %store dummy)
 
diff --git a/tests/publish.scm b/tests/publish.scm
index 0b92390900..6c710fe0a7 100644
--- a/tests/publish.scm
+++ b/tests/publish.scm
@@ -112,6 +112,14 @@ References: ~a~%"
        (call-with-input-string nar (cut restore-file <> temp)))
      (call-with-input-file temp read-string))))
 
+(test-equal "/nar/invalid"
+  404
+  (begin
+    (call-with-output-file (string-append (%store-prefix) "/invalid")
+      (lambda (port)
+        (display "This file is not a valid store item." port)))
+    (response-code (http-get (publish-uri (string-append "/nar/invalid"))))))
+
 (test-end "publish")
 
 
diff --git a/tests/store.scm b/tests/store.scm
index 394c06bc0f..de070eab23 100644
--- a/tests/store.scm
+++ b/tests/store.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.
 ;;;
@@ -837,6 +837,15 @@
          (file (add %store "foo" "Lowered.")))
     (call-with-input-file file get-string-all)))
 
+(test-equal "current-system"
+  "bar"
+  (parameterize ((%current-system "frob"))
+    (run-with-store %store
+      (mbegin %store-monad
+        (set-current-system "bar")
+        (current-system))
+      #:system "foo")))
+
 (test-assert "query-path-info"
   (let* ((ref (add-text-to-store %store "ref" "foo"))
          (item (add-text-to-store %store "item" "bar" (list ref)))
@@ -847,6 +856,21 @@
                   (string->utf8
                    (call-with-output-string (cut write-file item <>))))))))
 
+(test-assert "path-info-deriver"
+  (let* ((b (add-text-to-store %store "build" "echo $foo > $out" '()))
+         (s (add-to-store %store "bash" #t "sha256"
+                          (search-bootstrap-binary "bash"
+                                                   (%current-system))))
+         (d (derivation %store "the-thing"
+                        s `("-e" ,b)
+                        #:env-vars `(("foo" . ,(random-text)))
+                        #:inputs `((,b) (,s))))
+         (o (derivation->output-path d)))
+    (and (build-derivations %store (list d))
+         (not (path-info-deriver (query-path-info %store b)))
+         (string=? (derivation-file-name d)
+                   (path-info-deriver (query-path-info %store o))))))
+
 (test-end "store")