diff --git a/debian/rules b/debian/rules
index 6eae824..75a5f32 100755
--- a/debian/rules
+++ b/debian/rules
@@ -70,7 +70,7 @@ ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS) $(DEB_BUILD_PROFILES)))
 	ln -vis /usr/bin/eperl $(o)/wml_test/tests/installation/lib/wml/exec/wml_p3_eperl
 	ln -vis /usr/bin/m4    $(o)/wml_test/tests/installation/lib/wml/exec/wml_p4_gm4
 	ln -vis /usr/bin/slice $(o)/wml_test/tests/installation/lib/wml/exec/wml_p9_slice
-	sed -e 's:/usr/\(lib\|share\)/wml:$(o)/wml_test/tests/installation/\1/wml:g; s:\(WML_LOC_.*\)=/usr:\1=$(o)/wml_test/tests/installation:g;' \
+	sed -e 's:^\(my $$EXEC_DIR *=\).*:\1 "$(o)/wml_test/tests/installation/lib/wml/exec";:g; s:/usr/\(lib\|share\)/wml:$(o)/wml_test/tests/installation/\1/wml:g; s:\(WML_LOC_.*\)=/usr:\1=$(o)/wml_test/tests/installation:g;' \
 	    -i $(o)/wml_test/tests/installation/bin/wm? \
 	       $(o)/wml_test/tests/installation/lib/wml/exec/wml_p* \
 	       $(o)/wml_test/tests/installation/lib/perl5/TheWML/*.pm \
diff --git a/wml_backend/p9_slice/CMakeLists.txt b/wml_backend/p9_slice/CMakeLists.txt
new file mode 100644
index 0000000..7ac358d
--- /dev/null
+++ b/wml_backend/p9_slice/CMakeLists.txt
@@ -0,0 +1,50 @@
+SET(BASENAME "slice")
+SET(src "${CMAKE_CURRENT_SOURCE_DIR}/${BASENAME}_main.pl")
+SET(destbase "${BASENAME}.pl")
+SET(dest "${CMAKE_CURRENT_BINARY_DIR}/${destbase}")
+
+SET (yytab_base "SliceTermParser.pm")
+
+SET (yytab "${CMAKE_CURRENT_SOURCE_DIR}/${yytab_base}")
+# Workaround for git clone SNAFU.
+EXECUTE_PROCESS(
+    COMMAND "cmake" "-E" "touch_nocreate" "${yytab}"
+)
+
+ADD_CUSTOM_COMMAND(
+    OUTPUT "${yytab}"
+    COMMAND "pbyacc"
+    ARGS "-l" "-P" "SliceTermParser" "slice_term.y"
+    COMMAND "${PERL_EXECUTABLE}"
+    ARGS "-i" "-lp" "./process-SliceTerm.pl" "./SliceTermParser.pm"
+    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+    DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/slice_term.y"
+)
+
+INSTALL (
+    FILES "${yytab}"
+    DESTINATION "${PKGDATADIR}"
+)
+
+PREPROCESS_PATH_PERL_WITH_FULL_NAMES(
+    "${BASENAME}_preproc" "${src}" "${dest}"
+)
+
+SET(INST_BASE "wml_p9_${BASENAME}")
+
+SET (POD2MAN_SOURCE_IS_IN_BINARY)
+SET (pod_dests )
+INST_RENAME_POD2MAN(
+    "pod_dests" "${BASENAME}.pod" "${BASENAME}" "1" "${INST_BASE}"
+)
+
+ADD_CUSTOM_TARGET(
+    "${BASENAME}_pod" ALL
+    DEPENDS ${pod_dests} ${yytab}
+)
+
+INSTALL(
+    PROGRAMS "${dest}"
+    DESTINATION "${WML_LIBEXE_DIR}"
+    RENAME "${INST_BASE}"
+)
diff --git a/wml_backend/p9_slice/COPYING b/wml_backend/p9_slice/COPYING
new file mode 100644
index 0000000..2f29635
--- /dev/null
+++ b/wml_backend/p9_slice/COPYING
@@ -0,0 +1,5 @@
+GPLv2-or-later. See:
+
+* https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+
+* https://www.gnu.org/licenses/gpl-3.0.en.html
diff --git a/wml_backend/p9_slice/ChangeLog b/wml_backend/p9_slice/ChangeLog
new file mode 100644
index 0000000..bbb3040
--- /dev/null
+++ b/wml_backend/p9_slice/ChangeLog
@@ -0,0 +1,303 @@
+       _ _
+   ___| (_) ___ ___
+  / __| | |/ __/ _ \
+  \__ \ | | (_|  __/
+  |___/_|_|\___\___|
+
+  ChangeLog
+
+  This file summarizes *all* types of changes to the Slice sources,
+  i.e. changes between each patchlevel (1.x.y->1.x.(y+1) and
+  1.x.y->1.(x+1).0). Take this logfile for concrete and detailed
+  information about every single change.
+  ___________________________________________________________________________
+
+  Changes between 1.3.8 and ???:
+
+    *) Checks on file errors (20-Apr-2002):
+       File operations are checked and SLICE aborts if an error is detected.
+       [Denis Barbier]
+
+    *) Fix -y flag (19-Apr-2002):
+       Slice did not abort with 's' or 'z' policy set to 3.
+       [Denis Barbier]
+
+  Changes between 1.3.7 and 1.3.8:
+
+    *) New -y flag (12-Jan-2002):
+       This flag changes output policy, by defining which action is to be
+       taken when unknown slice sets are requested, or when input is empty.
+       Note that an undefined set used was previously considered as an error,
+       and it is now silently ignored by default.
+       [Denis Barbier]
+
+    *) Change detection of Perl modules (12-Jan-2002):
+       [Denis Barbier]
+
+    *) Cosmetic changes (22-Jul-2001):
+       Remove ampersands before function calls.
+       [Denis Barbier]
+
+    *) Upgrade to Autoconf 2.50 (22-Jul-2001):
+       [Denis Barbier]
+
+    *) Fix compilation of Bit::Vector with perl < 5.005 (20-Jun-2001):
+       Apply the 2001-08-27 patch by Max H. Duenki.
+       [Denis Barbier]
+
+    *) Upgraded to Bit::Vector 6.0 (04-May-2001):
+       [Denis Barbier]
+
+  Changes between 1.3.6 and 1.3.7:
+
+    *) Fix an infinite loop in slice 1.3.6  (27-Aug-2000):
+       Previous patch about speed improvements made slice hang up with
+       some files.  This patch has been entirely revisited.
+       [Josip Rodin <joy@cibalia.gkvk.hr>]
+
+    *) New `all except' operator (27-Aug-2000):
+       The wildcard sign accepts a new syntax.  When followed by braces,
+       it replaces ``all strings except the one enclosed within braces''.
+       This construct could not be emulated with previous operators with
+       nested slices.
+       [Denis Barbier]
+
+    *) Fix `%' operator (27-Aug-2000):
+       This operator, which is a synonym for `n' i.e. intersection of
+       slices, was only partially implemented
+       [Denis Barbier]
+
+    *) Fix compilation of Bit::Vector with perl < 5.005 (27-Aug-2000):
+       [Max H. Duenki <duenki@isi.ee.ethz.ch>]
+
+  Changes between 1.3.5 and 1.3.6:
+
+    *) Improve processing speed on large files (29-Jul-2000):
+       On very large files, this program was dramatically slow.
+       A speed-up factor of 15 is obtained on a 300KB file containing
+       16000 slices.
+       [Denis Barbier]
+
+    *) Fix compilation on threaded Perl 5.6.0 (29-Jul-2000):
+       [Denis Barbier]
+
+    *) Upgrade of Bit::Vector (28-Jul-2000):
+       Upgraded Bit::Vector from version 5.7 to 5.8.
+       [Ralf S. Engelschall]
+
+    *) Upgraded to GNU shtool 1.5.0 (01-Jul-2000):
+       Upgraded to GNU shtool 1.5.0. This involved especially a major
+       adjustment because of the rewritten "shtool version" command.
+       [Ralf S. Engelschall]
+
+  Changes between 1.3.4 and 1.3.5:
+
+    *) Fix compilation on FreeBSD  (27-Apr-2000):
+       [Denis Barbier]
+
+    *) Fix detection of Perl at configure time  (27-Apr-2000):
+       Perl 5.6.0 uses a versioning scheme different than previous
+       versions, which breaks our detection scheme.
+       [Denis Barbier]
+
+  Changes between 1.3.3 and 1.3.4:
+
+    *) Use of the TMPDIR environment variable (28-Aug-1999):
+       To conform with POSIX standard, this variable contains
+       the directory name where temporary files are kept. By default,
+       this directory is /tmp.
+       [Thomas Roessler <roessler@guug.de>]
+
+    *) Use GNU shtool for configuring (25-Aug-1999):
+       All scripts in etc/ sub-directories were still replaced by
+       Ralf's shtool since 01-Jul-1999. They are now removed.
+       [Denis Barbier]
+
+    *) Write empty file (23-Aug-1999):
+       An empty output implies an empty file. Previous versions
+       did not write empty files.
+       [Denis Barbier]
+
+    *) Fix installation of Perl modules (05-Jul-1999):
+       On some platforms, Perl modules are not installed according
+       to the prefix passed to the configure command-line.
+       Rules in Makefiles now invoke pure_perl_install
+       [Tobias Oetiker <oetiker@ee.ethz.ch>]
+
+  Changes between 1.3.2 and 1.3.3:
+
+    *) Upgrade Perl modules (21-May-1999):
+       - Bit-Vector 5.6
+       - IO 1.20
+       - Getopt-Long 2.19
+       [Denis Barbier <barbier@imacs.polytechnique.fr>]
+
+    *) Fixed slice_term.y (10-May-1999):
+       An undefined slice reports a warning instead of an error
+       [Michael McNamara <mac@surefirev.com>]
+  ___________________________________________________________________________
+
+  Slice is now maintained by Denis Barbier <barbier@imacs.polytechnique.fr>
+  I've now changed the syntax of the ChangeLog file for more readability
+  ___________________________________________________________________________
+
+  Changes between 1.3.1 and 1.3.2
+      980218 - Upgraded to Bit-Vector 5.0b4
+             - Upgraded to IO 1.19
+             - Fixed copyright notice and FSF address
+
+  Changes between 1.3.0 and 1.3.1
+      980128 - fixed the "Some slices were not closed" error
+               message. Now the slice named are printed as
+               expected.
+             - Upgraded to IO 1.1804
+
+  Changes between 1.2.9 and 1.3.0
+      980106 - Added support for wildcarded slice at the -o
+               option. This is very useful to avoid endless
+               union-constructs in slice terms. To avoid
+               conflicts the intersection now uses the
+               characters [n%] instead of [n*].
+             - Upgraded to BIt::Vector 5.0b2
+             - Fixed Getopt::Long check in configure.in
+             - Added Version display to configure.in
+             - Added subdir movement display to Makefile.in
+             - Removed "All Rights Reserved" from copyright
+               messages because this conflicts with GNU GPL.
+             - Adjusted slice.pod for new features and added
+               Version, Copyright and See Also sections
+
+  Changes between 1.2.8 and 1.2.9
+      971228 - slice.1 now is installed as
+               PREFIX/man/man1/slice.1 instead of just
+               PREFIX/man/slice.1 [Thanks to Anthony Fok
+               <foka@gpu.srv.ualberta.ca> for patch]
+             - changed Perl module version check according to the
+               way WML does it [Thanks to Anthony Fok
+               <foka@gpu.srv.ualberta.ca> for patch]
+             - upgraded to GetoptLong 2.13
+             - upgraded to IO 1.1803
+
+  Changes between 1.2.7 and 1.2.8
+      971212 - disabled Perl warnings
+             - fixed lib/00README file
+             - fixed destroyed COPYING file
+             - adjusted ChangeLog file to WML format
+             - added longoptions to usage page
+             - changed -v to -V option
+             - changed -x to -v option
+             - added -h option
+
+  Changes between 1.2.6 and 1.2.7
+      971127 - upgraded to Bit::Vector 5.0b1
+
+  Changes between 1.2.5 and 1.2.6
+      971014 - upgraded to Getopt::Long 2.12
+      971112 - upgraded to IO 1.1801
+             - fixed nasty bug when some slices are used more
+               then once (for different output files but one with
+               a negation).  [Thanks to Sebastian Wilhelmi for
+               hint <wilhelmi@ira.uka.de>]
+             - fixed Debug output
+             - fixed Perl interpreter determination because of
+               Perl 5.004_04 where -v output changed.
+
+  Changes between 1.2.4 and 1.2.5
+      970828 - slightly changes the verbose and error messages
+             - slightly fixed slice.pod
+
+  Changes between 1.2.3 and 1.2.4
+      970819 - upgraded to Getopt::Long 2.10
+             - let slice accept empty input files without
+               complaining it
+             - added RESTRICTION section to slice.pod to make it
+               clear that anon end delimiters can lead to
+               problems.
+
+  Changes between 1.2.2 and 1.2.3
+      970815 - made it workable under Perl 5.003 again
+             - removed perl -c check in Makefile.in
+             - fixed distclean target
+             - fixed lib/Makefile.in
+             - fixed lib/getoptlong/Makefile.PL
+             - fixed lib/io/Makefile.PL
+             - disabled $Getopt::Long::getopt_compat option
+
+  Changes between 1.2.1 and 1.2.2
+      970814 - improved the %!slice support [Thanks to Andrew
+               Pimlott <pimlott@abel.MATH.HARVARD.EDU> for
+               providing the patch]
+             - overhauled the ChangeLog file format ;-)
+
+  Changes between 1.2.0 and 1.2.1
+      970812 - Perl 5.004 not needed, 5.003 works too.
+             - added support for ``%!slice ...'' lines which can
+               overwrite the options from within the file
+
+  Changes between 1.1.1 and 1.2.0
+      970715 - upgraded etc/newvers
+             - upgraded to Bit::Vector 4.2 module
+             - added --with-perl option to configure
+             - added IO package to lib/
+             - added etc/crunch
+             - added SLICE@ syntax (see slice.pod)
+      970805 - greatly overhauled and optimized the output
+               generation
+
+  Changes between 1.1.0 and 1.1.1
+      970523 - fixed problem with existing /tmp/x in configure,
+               no /tmp/ac.$$
+             - fixed new-patchlevel target in Makefile.in
+             - added fixperm script and fixperm target
+
+  Changes between 1.0.7 and 1.1.0
+      970423 - upgraded from Set::IntegerFast 3.2 to Bit::Vector
+               4.0 module
+
+  Changes between 1.0.6 and 1.0.7
+      970402 - again fixed MakeMaker install path determination.
+               in GNU autoconf again. Now it should really work
+               correctly ;_)
+
+  Changes between 1.0.5 and 1.0.6
+      970221 - fixed MakeMaker install path determination
+               in GNU autoconf again. Now it should work
+               correctly ;_)
+
+  Changes between 1.0.4 and 1.0.5
+      970215 - changed COPYRIGHT header to LICENSE header in file
+               LICENSE
+             - changed library hack with BEGIN to "use lib"
+               variant
+             - made autoconf part for MakeMaker install paths
+               more robust, at least for Linux
+             - the slice.1 is pre-generated because pod2man is
+               broken on some Linux machines
+             - added MKDIR to Makefile.in's install target
+
+  Changes between 1.0.3 and 1.0.4
+      970205 - fixed the lib/Makefile
+             - changed local() to my() where appropriate
+             - fixed a few bugs in slice.pod
+             - added "make update-version"
+
+  Changes between 1.0.2 and 1.0.3
+      970204 - updated to Steffen Beyers official
+               Set::IntegerFast 3.0 module from
+               Set-IntegerFast-3.2 bundle.
+
+  Changes between 1.0.1 and 1.0.2
+      970131 - fixed setting of empty sets where low = high+1
+             - added check for existing slice names
+
+  Changes between 1.0.0 and 1.0.1
+      970131 - changed signature of rse
+             - used new Set::IntegerFast::Fill_Interval method
+             - used new Set::IntegerFast::Size method
+             - fixed "make clean" inside lib/
+             - fixed "configure" target in Makefile
+             - fixed "make clean" for t/
+
+  Changes between *GENESIS* and 1.0.1
+      9701xx - *GENESIS*
+
diff --git a/wml_backend/p9_slice/LICENSE b/wml_backend/p9_slice/LICENSE
new file mode 100644
index 0000000..9a17272
--- /dev/null
+++ b/wml_backend/p9_slice/LICENSE
@@ -0,0 +1,37 @@
+LICENSE
+
+Slice -- Extract pre-defined slices of an ASCII file
+
+Copyright (c) 1997-2002 Ralf S. Engelschall.
+Copyright (c) 1999-2002 Denis Barbier.
+
+This program 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 2 of the 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+in the file COPYING along with this program; if not, write to
+
+  Free Software Foundation, Inc.
+  59 Temple Place - Suite 330
+  Boston, MA  02111-1307, USA
+
+Notice, that ``free software'' addresses the fact that this program
+is __distributed__ under the term of the GNU General Public License
+and because of this, it can be redistributed and modified under the
+conditions of this license, but the software remains __copyrighted__
+by the author. Don't intermix this with the general meaning of
+Public Domain software or such a derivated distribution label.
+
+The author reserves the right to distribute following releases of
+this program under different conditions or license agreements.
+
+                              Ralf S. Engelschall
+                              rse@engelschall.com
+                              www.engelschall.com
diff --git a/wml_backend/p9_slice/README b/wml_backend/p9_slice/README
new file mode 100644
index 0000000..92c568c
--- /dev/null
+++ b/wml_backend/p9_slice/README
@@ -0,0 +1,27 @@
+Slice -- Extract out pre-defined slices of an ASCII file
+
+Version 1.3.8 (10-Feb-2002)
+
+The slice program reads an input file and divide its prepared ASCII contents
+into possibly overlapping slices. These slices are determined by enclosing
+blocks which are defined by begin and end delimiters which have to be
+already in the file.   The final output gets calculated by a slice term
+consisting of slice names, set theory operators and optional round brackets.
+
+The latest release can be found on
+http://www.engelschall.com/sw/slice/
+
+Copyright (c) 1997-2002 Ralf S. Engelschall.
+Copyright (c) 1999-2002 Denis Barbier.
+
+This program is free software; it may be redistributed and/or modified only
+under the terms of the GNU General Public License, which may be found in the
+SLICE source distribution.  Look at the file COPYING.   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 either the GNU General Public License for more
+details.
+
+                            Ralf S. Engelschall
+                            rse@engelschall.com
+                            www.engelschall.com
diff --git a/wml_backend/p9_slice/SliceTermParser.pm b/wml_backend/p9_slice/SliceTermParser.pm
new file mode 100644
index 0000000..b1cd348
--- /dev/null
+++ b/wml_backend/p9_slice/SliceTermParser.pm
@@ -0,0 +1,498 @@
+# @(#)yaccpar 1.8 (Berkeley) 01/20/91 (JAKE-P5BP-0.6 04/26/98)
+package SliceTermParser;
+;##
+;##  slice_term.y -- YACC parser for slice terms
+;##  Copyright (c) 1997-2002 Ralf S. Engelschall.
+;##  Copyright (c) 1999-2002 Denis Barbier.
+;##
+
+package SliceTermParser;
+
+{
+    use strict;
+    use warnings;
+    my $YYTABLESIZE;
+    my $YYMAXTOKEN;
+    my $YYERRCODE;
+    my (@yylhs, @yylen, @yyname, $YYFINAL, @yygindex, @yycheck, @yytable, @yyrule);
+    my (@yydgoto, @yyrindex, @yysindex, @yydefred);
+    my $SLICE ;
+$SLICE=257;
+$YYERRCODE=256;
+@yylhs = (                                               -1,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,
+);
+@yylen = (                                                2,
+    1,    2,    2,    2,    3,    3,    3,    3,    3,    3,
+    3,    3,    3,
+);
+@yydefred = (                                             0,
+    0,    0,    0,    0,    0,    2,    3,    4,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,   13,    0,    0,
+    0,    0,    0,    0,    9,   10,
+);
+@yydgoto = (                                              5,
+);
+@yysindex = (                                           -33,
+  -60,  -33,  -33,  -33,   -7,    0,    0,    0,  -12,  -33,
+  -33,  -33,  -33,  -33,  -33,  -33,  -33,    0,  -31,  -31,
+   24,   24,  -36,  -36,    0,    0,
+);
+@yyrindex = (                                             0,
+    2,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,   15,   17,
+    9,   14,    3,    8,    0,    0,
+);
+@yygindex = (                                           135,
+);
+$YYTABLESIZE=224;
+@yytable = (                                              2,
+   17,    1,    5,    6,    0,   17,    4,    6,   11,    0,
+    0,   13,    0,   12,    7,    0,    8,    0,    0,    0,
+    0,    0,    0,    0,   17,    0,    0,    0,   18,   17,
+   13,    0,   11,    0,    0,   13,    0,   11,    1,    0,
+    0,    0,    1,    5,    1,    5,    1,    5,    6,   11,
+    6,   11,    6,   11,   12,    7,   12,    8,   12,    7,
+   17,    8,   15,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,   16,    0,    0,    0,    0,   16,   10,
+    0,   15,    0,    0,   10,   12,   15,    0,   14,    0,
+    0,    0,    3,    1,    5,    1,    5,   16,    0,    6,
+   11,    6,   16,    0,   12,   12,    7,   14,    8,   12,
+    0,    1,   14,    0,    0,    0,    0,   15,    1,    5,
+    0,    1,    5,    0,    6,   11,    0,    6,    0,    0,
+   12,    0,    0,   16,    0,    0,    7,    8,    9,    0,
+    0,    0,    0,   14,   19,   20,   21,   22,   23,   24,
+   25,   26,    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,    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,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    1,
+);
+@yycheck = (                                             33,
+   37,    0,    0,   64,   -1,   37,   40,    0,    0,   -1,
+   -1,   43,   -1,    0,    0,   -1,    0,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   37,   -1,   -1,   -1,   41,   37,
+   43,   -1,   45,   -1,   -1,   43,   -1,   45,   37,   -1,
+   -1,   -1,   41,   41,   43,   43,   45,   45,   41,   41,
+   43,   43,   45,   45,   41,   41,   43,   41,   45,   45,
+   37,   45,   94,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  110,   -1,   -1,   -1,   -1,  110,   92,
+   -1,   94,   -1,   -1,   92,  117,   94,   -1,  120,   -1,
+   -1,   -1,  126,   92,   92,   94,   94,  110,   -1,   92,
+   92,   94,  110,   -1,  117,   92,   92,  120,   92,  117,
+   -1,  110,  120,   -1,   -1,   -1,   -1,   94,  117,  117,
+   -1,  120,  120,   -1,  117,  117,   -1,  120,   -1,   -1,
+  117,   -1,   -1,  110,   -1,   -1,    2,    3,    4,   -1,
+   -1,   -1,   -1,  120,   10,   11,   12,   13,   14,   15,
+   16,   17,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
+   -1,   -1,   -1,  257,
+);
+$YYFINAL=5;
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+$YYMAXTOKEN=257;
+#if YYDEBUG
+@yyname = (
+"end-of-file",'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
+"'!'",'','','',"'%'",'','',"'('","')'",'',"'+'",'',"'-'",'','','','','','','','','','','','','','','',
+'','','',"'\@'",'','','','','','','','','','','','','','','','','','','','','','','','','','','',"'\\\\'",'',
+"'^'",'','','','','','','','','','','','','','','',"'n'",'','','','','','',"'u'",'','',"'x'",'','','','','',
+"'~'",'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
+'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
+'','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','',
+'','','','','','','','','','','','','',"SLICE",
+);
+@yyrule = (
+"\$accept : expr",
+"expr : SLICE",
+"expr : SLICE '\@'",
+"expr : '!' expr",
+"expr : '~' expr",
+"expr : expr 'x' expr",
+"expr : expr '^' expr",
+"expr : expr '\\\\' expr",
+"expr : expr '-' expr",
+"expr : expr 'n' expr",
+"expr : expr '%' expr",
+"expr : expr 'u' expr",
+"expr : expr '+' expr",
+"expr : '(' expr ')'",
+);
+#endif
+sub yyclearin {
+  my  $p;
+  ($p) = @_;
+  $p->{yychar} = -1;
+}
+sub yyerrok {
+  my  $p;
+  ($p) = @_;
+  $p->{yyerrflag} = 0;
+}
+sub new {
+  my $p = bless {}, $_[0];
+  $p->{yylex} = $_[1];
+  $p->{yyerror} = $_[2];
+  $p->{yydebug} = $_[3];
+  return $p;
+}
+sub YYERROR {
+  my  $p;
+  ($p) = @_;
+  ++$p->{yynerrs};
+  $p->yy_err_recover;
+}
+sub yy_err_recover {
+  my  $p;
+  ($p) = @_;
+  if ($p->{yyerrflag} < 3)
+  {
+    $p->{yyerrflag} = 3;
+    while (1)
+    {
+      if (($p->{yyn} = $yysindex[$p->{yyss}->[$p->{yyssp}]]) &&
+          ($p->{yyn} += $YYERRCODE) >= 0 &&
+          $p->{yyn} <= $#yycheck &&
+          $yycheck[$p->{yyn}] == $YYERRCODE)
+      {
+        warn("yydebug: state " .
+                     $p->{yyss}->[$p->{yyssp}] .
+                     ", error recovery shifting to state" .
+                     $yytable[$p->{yyn}] . "\n")
+                       if $p->{yydebug};
+        $p->{yyss}->[++$p->{yyssp}] =
+          $p->{yystate} = $yytable[$p->{yyn}];
+        $p->{yyvs}->[++$p->{yyvsp}] = $p->{yylval};
+        next yyloop;
+      }
+      else
+      {
+        warn("yydebug: error recovery discarding state ".
+              $p->{yyss}->[$p->{yyssp}]. "\n")
+                if $p->{yydebug};
+        return(undef) if $p->{yyssp} <= 0;
+        --$p->{yyssp};
+        --$p->{yyvsp};
+      }
+    }
+  }
+  else
+  {
+    return (undef) if $p->{yychar} == 0;
+    if ($p->{yydebug})
+    {
+      $p->{yys} = '';
+      if ($p->{yychar} <= $YYMAXTOKEN) { $p->{yys} =
+        $yyname[$p->{yychar}]; }
+      if (!$p->{yys}) { $p->{yys} = 'illegal-symbol'; }
+      warn("yydebug: state " . $p->{yystate} .
+                   ", error recovery discards " .
+                   "token " . $p->{yychar} . "(" .
+                   $p->{yys} . ")\n");
+    }
+    $p->{yychar} = -1;
+    next yyloop;
+  }
+0;
+} # yy_err_recover
+
+sub yyparse {
+  my  $p;
+  my $s;
+  ($p, $s) = @_;
+  if ($p->{yys} = $ENV{'YYDEBUG'})
+  {
+    $p->{yydebug} = int($1) if $p->{yys} =~ /^(\d)/;
+  }
+
+  $p->{yynerrs} = 0;
+  $p->{yyerrflag} = 0;
+  $p->{yychar} = (-1);
+
+  $p->{yyssp} = 0;
+  $p->{yyvsp} = 0;
+  $p->{yyss}->[$p->{yyssp}] = $p->{yystate} = 0;
+
+yyloop: while(1)
+  {
+    yyreduce: {
+      last yyreduce if ($p->{yyn} = $yydefred[$p->{yystate}]);
+      if ($p->{yychar} < 0)
+      {
+        if ((($p->{yychar}, $p->{yylval}) =
+            &{$p->{yylex}}($s)) < 0) { $p->{yychar} = 0; }
+        if ($p->{yydebug})
+        {
+          $p->{yys} = '';
+          if ($p->{yychar} <= $#yyname)
+             { $p->{yys} = $yyname[$p->{yychar}]; }
+          if (!$p->{yys}) { $p->{yys} = 'illegal-symbol'; };
+          warn("yydebug: state " . $p->{yystate} .
+                       ", reading " . $p->{yychar} . " (" .
+                       $p->{yys} . ")\n");
+        }
+      }
+      if (($p->{yyn} = $yysindex[$p->{yystate}]) &&
+          ($p->{yyn} += $p->{yychar}) >= 0 &&
+          $p->{yyn} <= $#yycheck &&
+          $yycheck[$p->{yyn}] == $p->{yychar})
+      {
+        warn("yydebug: state " . $p->{yystate} .
+                     ", shifting to state " .
+              $yytable[$p->{yyn}] . "\n") if $p->{yydebug};
+        $p->{yyss}->[++$p->{yyssp}] = $p->{yystate} =
+          $yytable[$p->{yyn}];
+        $p->{yyvs}->[++$p->{yyvsp}] = $p->{yylval};
+        $p->{yychar} = (-1);
+        --$p->{yyerrflag} if $p->{yyerrflag} > 0;
+        next yyloop;
+      }
+      if (($p->{yyn} = $yyrindex[$p->{yystate}]) &&
+          ($p->{yyn} += $p->{'yychar'}) >= 0 &&
+          $p->{yyn} <= $#yycheck &&
+          $yycheck[$p->{yyn}] == $p->{yychar})
+      {
+        $p->{yyn} = $yytable[$p->{yyn}];
+        last yyreduce;
+      }
+      if (! $p->{yyerrflag}) {
+        &{$p->{yyerror}}('syntax error', $s);
+        ++$p->{yynerrs};
+      }
+      return(undef) if $p->yy_err_recover;
+    } # yyreduce
+    warn("yydebug: state " . $p->{yystate} .
+                 ", reducing by rule " .
+                 $p->{yyn} . " (" . $yyrule[$p->{yyn}] .
+                 ")\n") if $p->{yydebug};
+    $p->{yym} = $yylen[$p->{yyn}];
+    $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}+1-$p->{yym}];
+if ($p->{yyn} == 1) {
+{ $p->{yyval} = newvar($p, $s->[0], $p->{yyvs}->[$p->{yyvsp}-0]); my $t = $p->{yyval}; my $src = $p->{yyvs}->[$p->{yyvsp}-0]; $p->_out(sub { my ($self, $CFG) = @_; $self->_set_var($t , $CFG->{SLICE}->{SET}->{OBJ}->{$src}->Clone); return;}); }
+}
+if ($p->{yyn} == 2) {
+{ $p->{yyval} = newvar($p, $s->[0], $p->{yyvs}->[$p->{yyvsp}-1]); my $t = $p->{yyval}; my $src = $p->{yyvs}->[$p->{yyvsp}-1]; $p->_out(sub { my ($self, $CFG) = @_; $self->_set_var($t , $CFG->{SLICE}->{SET}->{OBJ}->{'NOV_'.$src}->Clone); return;}); }
+}
+if ($p->{yyn} == 3) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-0]; $p->_push_complement($p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 4) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-0]; $p->_push_complement($p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 5) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'ExclusiveOr', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 6) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'ExclusiveOr', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 7) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'Difference', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 8) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'Difference', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 9) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'Intersection', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 10) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'Intersection', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 11) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'Union', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 12) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-2]; $p->_push_mutate($p->{yyvs}->[$p->{yyvsp}-2], 'Union', $p->{yyvs}->[$p->{yyvsp}-0]); }
+}
+if ($p->{yyn} == 13) {
+{ $p->{yyval} = $p->{yyvs}->[$p->{yyvsp}-1]; }
+}
+    $p->{yyssp} -= $p->{yym};
+    $p->{yystate} = $p->{yyss}->[$p->{yyssp}];
+    $p->{yyvsp} -= $p->{yym};
+    $p->{yym} = $yylhs[$p->{yyn}];
+    if ($p->{yystate} == 0 && $p->{yym} == 0)
+    {
+      warn("yydebug: after reduction, shifting from state 0 ",
+            "to state $YYFINAL\n") if $p->{yydebug};
+      $p->{yystate} = $YYFINAL;
+      $p->{yyss}->[++$p->{yyssp}] = $YYFINAL;
+      $p->{yyvs}->[++$p->{yyvsp}] = $p->{yyval};
+      if ($p->{yychar} < 0)
+      {
+        if ((($p->{yychar}, $p->{yylval}) =
+            &{$p->{yylex}}($s)) < 0) { $p->{yychar} = 0; }
+        if ($p->{yydebug})
+        {
+          $p->{yys} = '';
+          if ($p->{yychar} <= $#yyname)
+            { $p->{yys} = $yyname[$p->{yychar}]; }
+          if (!$p->{yys}) { $p->{yys} = 'illegal-symbol'; }
+          warn("yydebug: state $YYFINAL, reading " .
+               $p->{yychar} . " (" . $p->{yys} . ")\n");
+        }
+      }
+      return ($p->{yyvs}->[1]) if $p->{yychar} == 0;
+      next yyloop;
+    }
+    if (($p->{yyn} = $yygindex[$p->{yym}]) &&
+        ($p->{yyn} += $p->{yystate}) >= 0 &&
+        $p->{yyn} <= $#yycheck &&
+        $yycheck[$p->{yyn}] == $p->{yystate})
+    {
+        $p->{yystate} = $yytable[$p->{yyn}];
+    } else {
+        $p->{yystate} = $yydgoto[$p->{yym}];
+    }
+    warn("yydebug: after reduction, shifting from state " .
+        $p->{yyss}->[$p->{yyssp}] . " to state " .
+        $p->{yystate} . "\n") if $p->{yydebug};
+    $p->{yyss}[++$p->{yyssp}] = $p->{yystate};
+    $p->{yyvs}[++$p->{yyvsp}] = $p->{yyval};
+  } # yyloop
+} # yyparse
+
+#   create new set variable
+my $tmpcnt = 0;
+sub newvar {
+local $SIG{__WARN__}=sub{print STDERR @_;exit(-1);};
+# use warnings FATAL => 'all';
+# die "oooookkkk";
+    my ($p, $CFG, $name) = @_;
+    my ($tmp);
+
+    if (( $CFG->{SLICE}->{SET}->{OBJ}->{"$name"} // '') eq '') {
+        main::printwarning("no such slice '$name'\n") if $p->{_undef};
+        #    The $p->{_undef} string is caught by caller, it is used
+        #    to trap warnings depending on the -y command line flag.
+        die $p->{_undef}."\n" if $p->{_undef} > 1;
+        $CFG->{SLICE}->{SET}->{OBJ}->{"$name"} =
+                $CFG->{SLICE}->{SET}->{OBJ}->{DEF0}->Clone;
+    }
+    $tmp = sprintf("\$T%03d", $tmpcnt++);
+    return $tmp;
+}
+
+#   the lexical scanner
+sub yylex {
+    my ($ctx) = @_;
+    my ($c, $val);
+
+    my ($CFG, $s, $wildcard) = @$ctx;
+    #   ignore whitespaces
+    $$s =~ s|^\s+||;
+
+    #   recognize end of string
+    return (0, 0) if ($$s eq '');
+
+    #   found a token
+    if ($$s =~ s|^([_A-Z0-9*{}]+)||) {
+        $val = $1;
+
+        #   if its a wildcarded slice name we have
+        #   to construct the slice union on-the-fly
+        if ($val =~ m|\*|) {
+            my $pat = $val;
+            $pat =~ s|\*|\.\*|g;
+
+            #   treat special *{...} sequence
+            my $excl = '';
+            while ($pat =~ s|^(.*?)\.\*\{([_A-Z0-9]+)\}(.*)$|$1\.\*$3|) {
+                my $temp = $1 . $2 . $3;
+                $temp =~ s|\.\*\{[_A-Z0-9]+\}|\.\*|g;
+                $excl .= "return 1 if m/^$temp\$/;";
+            }
+            my $sub_excl = eval "sub { \$_ = shift; $excl; return 0}";
+
+            my $slice;
+            my @slices = ();
+            foreach $slice (keys(%{$CFG->{SLICE}->{SET}->{ASC}})) {
+                if ($slice =~ m|^$pat$|) {
+                    push(@slices, $slice) unless &$sub_excl($slice);
+                }
+            }
+            if (@slices == 1) {
+                $val = $slices[0];
+            }
+            elsif (@slices > 1) {
+                $$s = join('u', @slices).')'.$$s;
+                return( ord('('), 0);
+            }
+            else {
+                main::printwarning("no existing slice matches `$val'\n") if $wildcard;
+                #    The $wildcard string is caught by caller, it is used
+                #    to trap warnings depending on the -y command line flag.
+                die $wildcard."\n" if $wildcard > 1;
+            }
+        }
+        return ($SLICE, $val);
+    }
+
+    #   else give back one plain character
+    $c = substr($$s, 0, 1);
+    $$s = substr($$s, 1);
+    return (ord($c), 0);
+}
+
+#   and error function
+sub yyerror {
+    my ($msg, $s) = @_;
+    die "$msg at $$s.\n";
+}
+
+sub _out {
+    my ($p, $item) = @_;
+    push(@{$p->{_OUT}}, $item);
+    return;
+}
+sub _push_complement {
+    my ($p, $v) = @_;
+    $p->_out(sub{my ($self)=@_;return $self->_complement_var($v);});
+    return;
+}
+sub _push_mutate {
+    my ($p, @args) = @_;
+    $p->_out(sub{my ($self)=@_;return $self->_mutate_var(@args);});
+    return;
+}
+
+#
+#  The top-level function which gets called by the user
+#
+#  ($cmds, $var) = SliceTerm::Parse($term, $status);
+#
+
+package SliceTerm;
+
+sub Parse {
+    my ($CFG, $str, $status) = @_;
+
+    my $p = SliceTermParser->new(\&SliceTermParser::yylex, \&SliceTermParser::yyerror, 0);
+    $p->{_OUT} = [];
+    $p->{_undef} = $status->{u};
+    # $p->yyclearin;
+    my $var = eval {$p->yyparse([$CFG, \$str, $status->{w}]);};
+    if ($@ =~ s/^(\d)$//) {
+        main::error("Execution stopped\n") if $1 > 2;
+        return ();
+    }
+    return ($p->{_OUT}, $var);
+}
+
+}
+
+package main;
+
+1;
+##EOF##
+1;
diff --git a/wml_backend/p9_slice/process-SliceTerm.pl b/wml_backend/p9_slice/process-SliceTerm.pl
new file mode 100644
index 0000000..b444427
--- /dev/null
+++ b/wml_backend/p9_slice/process-SliceTerm.pl
@@ -0,0 +1,5 @@
+use strict;
+use warnings;
+s/ +\z//ms;
+s/"'\@'"/"'\\\@'"/g;
+s%"expr : SLICE '\@'",%"expr : SLICE '\\\@'",%g
diff --git a/wml_backend/p9_slice/slice.pod b/wml_backend/p9_slice/slice.pod
new file mode 100644
index 0000000..dfd24cf
--- /dev/null
+++ b/wml_backend/p9_slice/slice.pod
@@ -0,0 +1,374 @@
+=encoding utf8
+
+=head1 NAME
+
+Slice -- Extract pre-defined slices from an ASCII file
+
+=head1 SYNOPSIS
+
+B<slice>
+[B<-v>]
+[B<-y> I<outputpolicy>]
+[B<-o> I<sliceterm>:I<outputfile>[@I<chmodcmd>][#I<outputpolicy>] ..]
+[I<inputfile>]
+
+B<slice>
+[B<-V>]
+[B<-h>]
+
+=head1 VERSION
+
+@SLICE_VERSION@
+
+=head1 DESCRIPTION
+
+=head2 Input Principle
+
+The F<slice> program reads I<inputfile> (or from F<STDIN> if I<inputfile> is
+not given or equal ``C<->'') and divides its already prepared ASCII contents
+into possibly overlapping areas, called I<slices>.   These slices are
+determined by enclosing blocks defined by begin and end delimiters which have
+to be I<already> in the file. These block delimiters use the syntax
+
+  [NAME: ... :NAME]
+
+or alternatively (if there is no misinterpretation possible, i.e. no
+overlapping or stacked slices)
+
+  [NAME: ... :]
+
+
+The I<NAME> identifier has to match against the regular expression
+``C<[_A-Z0-9]+>'', i.e. I<NAME> is a string consisting only of uppercase
+letters, digits or underscore characters.
+
+There can be as many such slice definitions as you like and there can be more
+than one slice with the same name. The resulting slice is the union of all
+equal named slices. Actually use this to spread a big slice over disjunct
+peaces of I<inputfile>.
+
+=head2 Output Selection Scheme
+
+The final output data gets calculated by a slice term consisting of slice
+names and set theory operators. The following syntax is recognized (in order
+of LR(1) grammar parsing) for slice terms:
+
+=over
+
+=item SLICE_TERM ::= C<NAME>
+
+The slice NAME itself. This name has to match against the regex
+``C<[_A-Z0-9*{}]+>''. Here two cases are possible: C<NAME> is either a plain
+slice name consisting only of uppercase letters, digits or an underscore
+character. Or it is a wildcarded slice name indicated by an asterisk
+character.
+
+The first variant just expands to the union of all slices named exactly
+C<NAME>.  The second variant expands to the union of all slices which match
+against the wildcard pattern C<NAME>. Here the asterisk has the semantical
+meaning of none or any number of characters.  There is one special case,
+when the asterisk is immediately followed by characters enclosed within
+braces, it means none or any number of characters, but not this sequence
+of characters.
+
+=item SLICE_TERM ::= C<!NAME> | C<~NAME>
+
+The B<complement> of slice NAME (i.e. ALL\NAME).
+
+In formula: {x in ALL: x B<not> in NAME}
+
+=item SLICE_TERM ::= C<NAME1xNAME2>, C<NAME1^NAME2>
+
+The B<exclusive-or> relation between slice NAME1 and slice NAME2. In set theory
+also called B<symmetric difference>: (NAME1uNAME2)\(NAME1nNAME2) or alternatively
+(NAME1n!NAME2)u(!NAME1nNAME2).
+
+In formula: {x in ALL: (x in NAME1 or x in NAME2) and not (x in NAME1 and x in
+NAME2)}.
+
+=item SLICE_TERM ::= C<NAME1\NAME2>, C<NAME1-NAME2>
+
+The B<difference> of slice NAME1 and slice NAME2, i.e. NAME1 minus NAME2.
+
+In formula: {x in ALL: x in NAME1 B<and> x B<not> in NAME2}
+
+=item SLICE_TERM ::= C<NAME1nNAME2> | C<NAME1%NAME2>
+
+The B<intersection> of slice NAME1 and slice NAME2.
+
+In formula: {x in ALL: x in NAME1 B<and> x in NAME2}
+
+=item SLICE_TERM ::= C<NAME1uNAME2>, C<NAME1+NAME2>
+
+The B<union> of slice NAME1 and slice NAME2.
+
+In formula: {x in ALL: x in NAME1 B<or> x in NAME2}
+
+=item SLICE_TERM ::= C<(> SLICE_TERM C<)>
+
+A grouped slice term. Use this to force a different order of evaluation.
+By default, all operators are left-associative, except complement which
+is right-associative.  Operators are listed below from lowest to highest
+precedence:
+
+    -  u  x  n  !
+
+=back
+
+=head2 Advanced Selection: Slice Levels
+
+Because slices can be overlapping and stacked, a definition level is assigned
+to each slice while the input is parsed. These levels range from 1 to the
+maximum encountered (the level 0 is the whole file, i.e. C<ALL>).  When a
+slice begins, it is assigned the lowest free level, beginning with level 1. As
+long as one level is in use, it cannot be assigned again until the end
+delimiter of the corresponding slice is seen.
+
+An example:
+
+     [A:[B::B]:A][C:[D:[E::C]:D][F::E]:F]
+
+  3                     E-----------E
+  2      B--B        D--------D
+  1   A--------A  C--------C     F-----F
+  0
+
+Here slice A is assigned level 1. Then B is assigned level 2 because level 1
+is still in use by A. Then the end of B is reached, level 2 is freed.  Then
+the end of A is reached and level 1 is also free now, so C is assigned level 1
+again. Now only level 1 is in use, so D is assigned level 2. Then E is
+assigned level 3. Then the end of C is seen and level 1 freed. Then the end of
+D is seen and level 2 is freed. Now F begins and because only level 3 is in
+use, it gets level 1 assigned. Then the end of E frees level 3 and the end of
+F frees level 1. Finally no levels are still in use. This indicates that the
+slicing is correct.
+
+If there are any used levels left at the end of this process this indicates an
+input error and F<slice> responds with an error message displaying the still
+open slices.
+
+This complicated level mechanism is needed for granular set operations where
+particular slices should be included or excluded only. So, to make life
+easier, a few pseudo-slices are automatically defined:
+
+=over
+
+=item C<DEFn>
+
+The union of all user-defined slices at exactly level n (0 <= n <= oo).
+
+=item C<UNDEFn>
+
+The union of all B<non>-user-defined slices at exactly level n (0 <= n <= oo).
+This actually is just C<!DEFn>.
+
+=item C<DEF>
+
+The union of all user-defined slices at B<all> levels, beginning at level
+B<1>.  This actually is the union of all C<DEFn> slices.
+
+=item C<UNDEF>
+
+The union of all B<non>-user-defined slices at B<all> levels, beginning with
+B<1>. This actually is just C<!DEF>.
+
+=item C<ALL>
+
+The whole file. This actually is just C<UNDEF0>, because at level 0 there are
+no user defined slices, so all is undefined.
+
+=item I<NAME>C<@>
+
+This is the slice I<NAME> minus the union of all C<DEFn> slices with min(NAME)
+<= n <= oo. Here min(NAME) is the lowest level plus one where I<NAME> ever
+occurred.  You can read this as ``NAME without all other slices at higher
+levels which overwrite it''. This sounds a little bit crazy, but actually is
+the most important construct. Try to understand it or your slice terms become
+very complicated.
+
+=back
+
+=head1 OPTIONS
+
+=over
+
+=item [B<-y> I<outputpolicy>]
+
+This flag changes output policy depending on events: C<u> when an
+undefined set is encountered, C<w> for an unmatched wildcard set, C<z> when
+output is empty and C<s> if it only consists of whitespace characters.
+Each letter is followed by a digit telling which action is bound to such
+events: C<0> to ignore such events, C<1> to display a warning message
+and continue, C<2> to skip concerned file and continue, and C<3> to
+abort with an error message.
+
+This flag consists of one or more events specifications, and default is
+C<u0w0s0z0>.
+
+=item [B<-o> I<sliceterm>:I<outputfile>[@I<chmodcmd>][#I<outputpolicy>] ..]
+
+This redirects the output to a file. Usually the whole file will be send to
+C<STDOUT> (same as C<ALL:->). You can use this option I<more than once> to
+output to more than one file while the corresponding I<sliceterm> determines
+which output data will be included into each output file.
+
+The optional I<chmodcmd> string is intended for specifying options for the
+F<chmod> command, which is applied to I<outputfile> after writing. For
+instance use ``C<a+r>'' to make sure the file is readable by a webserver of
+``C<u+x>'' to create a file with the execution bit set (usually used for SSI
+files on a webserver with the C<XBitHack> option available).
+
+The optional I<outputpolicy> string allows changing output policy for
+only this output file without changing its global meaning.  See above
+for informations on output policy.
+
+Be careful here: When you use parenthesis or asterisks inside I<sliceterm> you
+have to make sure it is really passed to F<slice> this way, i.e. usually you
+have to escape these characters from interpolation by the used shell. Do this
+either by adding backslashes in front of these characters or just surround the
+complete option argument with single quotes ('').
+
+=item B<-v>
+
+This sets verbose mode where some processing information will be given on the
+console for debugging purpose.
+
+=item B<-V>
+
+Displays the version identification string.
+
+=item B<-h>
+
+Displays the usage page.
+
+=back
+
+=head1 SPECIAL FEATURE
+
+Sometimes it can be very useful to be able to provide command line options
+directly within the input file, for instance to setup one or more B<-o>
+options. For this F<slice> recognizes lines of the form
+
+   %!slice OPTIONS
+
+in the input file and automatically adds OPTIONS to the argument line options.
+These lines have to start in column 0.
+
+Example:
+
+   %!slice -oTOC:contents.txt
+
+=head1 EXAMPLE
+
+Assume the following simple multi-language article file F<article.src>,
+written in HTML:
+
+  <html>
+  <head>
+  <title>[EN:Titlepage:][DE:Titelseite:]</title>
+  </head>
+  <body>
+
+  <center>
+  <h1>[EN:The Title itself:][DE:Der Titel selbst:]</h1>
+  </center>
+
+  <blockquote>
+  [EN:...English Abstract...:]
+  [DE:...Deutsche Zusammenfassung...:]
+  </blockquote>
+
+  [EN:...English Text...:]
+  [DE:...Deutscher Text...:]
+
+  </body>
+  </html>
+
+The command
+
+  slice -o ENuUNDEF:article.html.en -o DEuUNDEF:article.html.de
+
+then creates the following to files:
+
+=over
+
+=item F<article.html.en>:
+
+  <html>
+  <head>
+  <title>Titlepage</title>
+  </head>
+  <body>
+
+  <center>
+  <h1>The Title itself</h1>
+  </center>
+
+  <blockquote>
+  ...English Abstract...
+  </blockquote>
+
+  ...English Text...
+  </body>
+  </html>
+
+=item F<article.html.de>:
+
+  <html>
+  <head>
+  <title>Titelseite</title>
+  </head>
+  <body>
+
+  <center>
+  <h1>Der Titel selbst</h1>
+  </center>
+
+  <blockquote>
+  ...Deutsche Zusammenfassung...
+  </blockquote>
+
+  ...Deutscher Text...
+  </body>
+  </html>
+
+=back
+
+=head1 RESTRICTION
+
+The current implementation only handles anonymous end delimiters ``C<:]>''
+correct in clear cases where no mis-interpretation is possible, i.e. when no
+overlapping occurs. For instance in
+
+   ...[A:...[B:...:A]...:]...
+
+the end delimiter is not correctly assign to the `B' slice. So, be careful
+when using anonymous end delimiters in overlapping situations. Pure stacking
+like
+
+   ...[A:...[B:...:]...:]...
+
+is allowed and handled correctly, but only when you interpret this as
+
+   ...[A:...[B:...:B]...:A]...
+
+=head1 COPYRIGHT
+
+  Copyright (c) 1997-2002 Ralf S. Engelschall.
+  Copyright (c) 1999-2002 Denis Barbier.
+
+=head1 SEEALSO
+
+Slice Home: http://www.engelschall.com/sw/slice/
+
+=head1 AUTHORS
+
+  Ralf S. Engelschall
+  rse@engelschall.com
+  www.engelschall.com
+
+  Denis Barbier
+  barbier@engelschall.com
+
+=cut
+
diff --git a/wml_backend/p9_slice/slice_main.pl b/wml_backend/p9_slice/slice_main.pl
new file mode 100644
index 0000000..bdb9c1f
--- /dev/null
+++ b/wml_backend/p9_slice/slice_main.pl
@@ -0,0 +1,14 @@
+#!@PATH_PERL@
+eval 'exec @PATH_PERL@ -S $0 ${1+"$@"}'
+    if $running_under_some_shell;
+
+use strict;
+use warnings;
+
+#   bootstrapping private installed modules
+use lib '@INSTALLPRIVLIB@';
+use lib '@INSTALLARCHLIB@';
+use TheWML::Backends::Slice::Main ();
+
+TheWML::Backends::Slice::Main->new( argv => [@ARGV] )->main;
+
diff --git a/wml_backend/p9_slice/slice_term.y b/wml_backend/p9_slice/slice_term.y
new file mode 100644
index 0000000..1e7a3f1
--- /dev/null
+++ b/wml_backend/p9_slice/slice_term.y
@@ -0,0 +1,179 @@
+%{
+##
+##  slice_term.y -- YACC parser for slice terms
+##  Copyright (c) 1997-2002 Ralf S. Engelschall.
+##  Copyright (c) 1999-2002 Denis Barbier.
+##
+
+package SliceTermParser;
+
+{
+    use strict;
+    use warnings;
+    my $YYTABLESIZE;
+    my $YYMAXTOKEN;
+    my $YYERRCODE;
+    my (@yylhs, @yylen, @yyname, $YYFINAL, @yygindex, @yycheck, @yytable, @yyrule);
+    my (@yydgoto, @yyrindex, @yysindex, @yydefred);
+    my $SLICE ;
+%}
+
+%token SLICE
+
+%left '\\' '-'
+%left 'u' '+'
+%left 'x' '^'
+%left 'n' '%'
+
+%right '!' '~'
+
+%%
+expr:   SLICE           { $$ = newvar($p, $s->[0], $1); my $t = $$; my $src = $1; $p->_out(sub { my ($self, $CFG) = @_; $self->_set_var($t , $CFG->{SLICE}->{SET}->{OBJ}->{$src}->Clone); return;}); }
+    |  SLICE '@'          { $$ = newvar($p, $s->[0], $1); my $t = $$; my $src = $1; $p->_out(sub { my ($self, $CFG) = @_; $self->_set_var($t , $CFG->{SLICE}->{SET}->{OBJ}->{'NOV_'.$src}->Clone); return;}); }
+    |   '!' expr        { $$ = $2; $p->_push_complement($2); }
+    |   '~' expr        { $$ = $2; $p->_push_complement($2); }
+    |   expr 'x' expr   { $$ = $1; $p->_push_mutate($1, 'ExclusiveOr', $3); }
+    |   expr '^' expr   { $$ = $1; $p->_push_mutate($1, 'ExclusiveOr', $3); }
+    |   expr '\\' expr  { $$ = $1; $p->_push_mutate($1, 'Difference', $3); }
+    |   expr '-' expr   { $$ = $1; $p->_push_mutate($1, 'Difference', $3); }
+    |   expr 'n' expr   { $$ = $1; $p->_push_mutate($1, 'Intersection', $3); }
+    |   expr '%' expr   { $$ = $1; $p->_push_mutate($1, 'Intersection', $3); }
+    |   expr 'u' expr   { $$ = $1; $p->_push_mutate($1, 'Union', $3); }
+    |   expr '+' expr   { $$ = $1; $p->_push_mutate($1, 'Union', $3); }
+    |   '(' expr ')'    { $$ = $2; }
+    ;
+%%
+
+#   create new set variable
+my $tmpcnt = 0;
+sub newvar {
+local $SIG{__WARN__}=sub{print STDERR @_;exit(-1);};
+# use warnings FATAL => 'all';
+# die "oooookkkk";
+    my ($p, $CFG, $name) = @_;
+    my ($tmp);
+
+    if (( $CFG->{SLICE}->{SET}->{OBJ}->{"$name"} // '') eq '') {
+        main::printwarning("no such slice '$name'\n") if $p->{_undef};
+        #    The $p->{_undef} string is caught by caller, it is used
+        #    to trap warnings depending on the -y command line flag.
+        die $p->{_undef}."\n" if $p->{_undef} > 1;
+        $CFG->{SLICE}->{SET}->{OBJ}->{"$name"} =
+                $CFG->{SLICE}->{SET}->{OBJ}->{DEF0}->Clone;
+    }
+    $tmp = sprintf("\$T%03d", $tmpcnt++);
+    return $tmp;
+}
+
+#   the lexical scanner
+sub yylex {
+    my ($ctx) = @_;
+    my ($c, $val);
+
+    my ($CFG, $s, $wildcard) = @$ctx;
+    #   ignore whitespaces
+    $$s =~ s|^\s+||;
+
+    #   recognize end of string
+    return (0, 0) if ($$s eq '');
+
+    #   found a token
+    if ($$s =~ s|^([_A-Z0-9*{}]+)||) {
+        $val = $1;
+
+        #   if its a wildcarded slice name we have
+        #   to construct the slice union on-the-fly
+        if ($val =~ m|\*|) {
+            my $pat = $val;
+            $pat =~ s|\*|\.\*|g;
+
+            #   treat special *{...} sequence
+            my $excl = '';
+            while ($pat =~ s|^(.*?)\.\*\{([_A-Z0-9]+)\}(.*)$|$1\.\*$3|) {
+                my $temp = $1 . $2 . $3;
+                $temp =~ s|\.\*\{[_A-Z0-9]+\}|\.\*|g;
+                $excl .= "return 1 if m/^$temp\$/;";
+            }
+            my $sub_excl = eval "sub { \$_ = shift; $excl; return 0}";
+
+            my $slice;
+            my @slices = ();
+            foreach $slice (keys(%{$CFG->{SLICE}->{SET}->{ASC}})) {
+                if ($slice =~ m|^$pat$|) {
+                    push(@slices, $slice) unless &$sub_excl($slice);
+                }
+            }
+            if (@slices == 1) {
+                $val = $slices[0];
+            }
+            elsif (@slices > 1) {
+                $$s = join('u', @slices).')'.$$s;
+                return( ord('('), 0);
+            }
+            else {
+                main::printwarning("no existing slice matches `$val'\n") if $wildcard;
+                #    The $wildcard string is caught by caller, it is used
+                #    to trap warnings depending on the -y command line flag.
+                die $wildcard."\n" if $wildcard > 1;
+            }
+        }
+        return ($SLICE, $val);
+    }
+
+    #   else give back one plain character
+    $c = substr($$s, 0, 1);
+    $$s = substr($$s, 1);
+    return (ord($c), 0);
+}
+
+#   and error function
+sub yyerror {
+    my ($msg, $s) = @_;
+    die "$msg at $$s.\n";
+}
+
+sub _out {
+    my ($p, $item) = @_;
+    push(@{$p->{_OUT}}, $item);
+    return;
+}
+sub _push_complement {
+    my ($p, $v) = @_;
+    $p->_out(sub{my ($self)=@_;return $self->_complement_var($v);});
+    return;
+}
+sub _push_mutate {
+    my ($p, @args) = @_;
+    $p->_out(sub{my ($self)=@_;return $self->_mutate_var(@args);});
+    return;
+}
+
+#
+#  The top-level function which gets called by the user
+#
+#  ($cmds, $var) = SliceTerm::Parse($term, $status);
+#
+
+package SliceTerm;
+
+sub Parse {
+    my ($CFG, $str, $status) = @_;
+
+    my $p = SliceTermParser->new(\&SliceTermParser::yylex, \&SliceTermParser::yyerror, 0);
+    $p->{_OUT} = [];
+    $p->{_undef} = $status->{u};
+    # $p->yyclearin;
+    my $var = eval {$p->yyparse([$CFG, \$str, $status->{w}]);};
+    if ($@ =~ s/^(\d)$//) {
+        main::error("Execution stopped\n") if $1 > 2;
+        return ();
+    }
+    return ($p->{_OUT}, $var);
+}
+
+}
+
+package main;
+
+1;
+##EOF##
