[latex3-commits] [l3svn] branch master updated: Split out l3build as a separate product/repo

noreply at latex-project.org noreply at latex-project.org
Sun Jun 25 12:04:47 CEST 2017


This is an automated email from the git hooks/post-receive script.

joseph pushed a commit to branch master
in repository l3svn.

The following commit(s) were added to refs/heads/master by this push:
       new  da4d6c9   Split out l3build as a separate product/repo
da4d6c9 is described below

commit da4d6c9563f45f1ca5585d3b71aec8cd91ca8229
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Sun Jun 25 11:02:53 2017 +0100

    Split out l3build as a separate product/repo
    
    This means you need l3build.lua in the TeX tree: for updates that
    might require
    
        texlua build.lua install
    
    from a checkout of the l3build repo
    (git clone https://github.com/latex3/l3build.git) for 'burning edge'
    features.
    
    Note that as we largely disable TeX tree searching there is a copy
    of regression-test.tex here.
---
 build-config.lua                                   |    3 +-
 build.lua                                          |   13 +-
 contrib/build.lua                                  |   13 +-
 l3build/README.md                                  |   79 -
 l3build/build-testfiles-plain.lua                  |   17 -
 l3build/build-testfiles.lua                        |   16 -
 l3build/build.lua                                  |   45 -
 l3build/l3build.dtx                                | 1625 --------------
 l3build/l3build.ins                                |   56 -
 l3build/l3build.lua                                | 2317 --------------------
 l3build/testfiles-plain/plain-pdftex.lvt           |   18 -
 l3build/testfiles-plain/plain-pdftex.tlg           |   17 -
 .../testfiles-plain/support/regression-test.cfg    |    4 -
 l3build/testfiles/00-test-1.luatex.tlg             |   14 -
 l3build/testfiles/00-test-1.lvt                    |   18 -
 l3build/testfiles/00-test-1.tlg                    |   14 -
 l3build/testfiles/01-expect.dtx                    |   15 -
 l3build/testfiles/01-expect.ins                    |    6 -
 l3build/testfiles/support/regression-test.cfg      |   85 -
 l3experimental/build.lua                           |   12 +-
 l3experimental/l3str/build.lua                     |   12 +-
 l3experimental/xcoffins/build.lua                  |   14 +-
 l3experimental/xgalley/build.lua                   |   12 +-
 l3kernel/build.lua                                 |   13 +-
 l3packages/build.lua                               |   12 +-
 l3packages/l3keys2e/build.lua                      |   12 +-
 l3packages/xfp/build.lua                           |   14 +-
 l3packages/xfrac/build.lua                         |   12 +-
 l3packages/xparse/build.lua                        |   12 +-
 l3packages/xtemplate/build.lua                     |   12 +-
 l3trial/build.lua                                  |   12 +-
 l3trial/l3auxdata/build.lua                        |   17 +-
 l3trial/l3benchmark/build.lua                      |   12 +-
 l3trial/l3bigint/build.lua                         |   13 +-
 l3trial/l3check/build.lua                          |   12 +-
 l3trial/l3fp-extras/build.lua                      |   12 +-
 l3trial/l3hooks/build.lua                          |   12 +-
 l3trial/l3htoks/build.lua                          |   12 +-
 l3trial/l3image/build.lua                          |   10 +-
 l3trial/l3kernel-extras/build.lua                  |   11 +-
 l3trial/l3ldb/build.lua                            |   14 +-
 l3trial/l3str-format-new/build.lua                 |   12 +-
 l3trial/l3trace/build.lua                          |   12 +-
 l3trial/l3tree/build.lua                           |   12 +-
 l3trial/xbox/build.lua                             |   12 +-
 l3trial/xfont/build.lua                            |   12 +-
 46 files changed, 176 insertions(+), 4533 deletions(-)

diff --git a/build-config.lua b/build-config.lua
index ced5a67..2fd8c96 100644
--- a/build-config.lua
+++ b/build-config.lua
@@ -1,6 +1,6 @@
 -- Common settings for LaTeX3 development repo, used by l3build script
 
-checkdeps   = checkdeps   or {maindir .. "/l3kernel", maindir .. "/l3build"}
+checkdeps   = checkdeps   or {maindir .. "/l3kernel"}
 typesetdeps = typesetdeps or {maindir .. "/l3kernel"}
 unpackdeps  = unpackdeps  or {maindir .. "/l3kernel"}
 
@@ -14,6 +14,7 @@ checksuppfiles  = checksuppfiles  or
     "minimal.cls",
     "ot1enc.def",
     "regression-test.cfg",
+    "regression-test.tex",
     "SpecialCasing.txt",
     "UnicodeData.txt",
   }
diff --git a/build.lua b/build.lua
index f8d096d..d8c2b4f 100644
--- a/build.lua
+++ b/build.lua
@@ -7,17 +7,16 @@ bundle  = "LaTeX3"
 module  = ""
 
 -- A couple of custom variables: the order here is set up for 'importance'
-bundles      = {"l3build", "l3kernel", "l3packages", "l3experimental", "l3trial"}
+bundles      = {"l3kernel", "l3packages", "l3experimental", "l3trial"}
 checkbundles =
   {
-    "l3build",
     "l3kernel",
     "l3packages",
     "l3experimental",
     "l3trial",
     "contrib"
   }
-ctanbundles  = {"l3build", "l3kernel", "l3packages", "l3experimental"}
+ctanbundles  = {"l3kernel", "l3packages", "l3experimental"}
 
 -- Location of main directory: use Unix-style path separators
 maindir = "."
@@ -90,8 +89,6 @@ function main (target)
   end
 end
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/l3build/l3build.lua")
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/contrib/build.lua b/contrib/build.lua
index 1db0b62..bf1247c 100644
--- a/contrib/build.lua
+++ b/contrib/build.lua
@@ -13,7 +13,6 @@ maindir = ".."
 -- Non-standard settings
 checkdeps   =
   {
-    maindir .. "/l3build",
     maindir .. "/l3packages/l3keys2e",
     maindir .. "/l3packages/xfrac",
     maindir .. "/l3packages/xparse",
@@ -24,9 +23,9 @@ checksearch = true
 -- In contrib testing, stop processing at the first error
 checkopts = "-interaction=batchmode -halt-on-error"
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3build/README.md b/l3build/README.md
deleted file mode 100644
index d05d541..0000000
--- a/l3build/README.md
+++ /dev/null
@@ -1,79 +0,0 @@
-l3build: a testing and building system for LaTeX3
-=================================================
-
-Release 2017/05/29
-
-Overview
---------
-
-The `l3build` module is designed to support the development of
-high-quality LaTeX code by providing:
-* A unit testing system
-* Automated typesetting of code sources
-* A reliable packaging system for CTAN releases
-
-The bundle consists of a Lua script to run the tasks and a
-`.tex` file which provides the testing environment. These were
-originally developed for supporting LaTeX3 development but
-are designed such that they can be readily used by others. Full
-documentation is provided.
-
-Discussion
-----------
-
-Discussion concerning the approach, suggestions for improvements,
-changes, additions, _etc._ should be addressed to the list
-[LaTeX-L](http://news.gmane.org/group/gmane.comp.tex.latex.latex3).
-
-You can subscribe to this list by sending mail to
-
-    listserv at urz.uni-heidelberg.de
-
-with the body containing
-
-    subscribe LATEX-L  <Your-First-Name> <Your-Second-Name>
-
-Issues
-------
-
-The issue tracker for LaTeX3 is currently located
-[on GitHub](https://github.com/latex3/latex3/issues).
-
-Please report specific issues with LaTeX3 code there; more general
-discussion should be directed to the [LaTeX-L list](#Discussion).
-
-The LaTeX3 Project
-------------------
-
-Development of LaTeX3 is carried out by
-[The LaTeX3 Project](http://www.latex-project.org/latex3.html). Currently,
-the team members are
-
-* Johannes Braams
-* David Carlisle
-* Robin Fairbairns
-* Morten Høgholm
-* Bruno Le Floch
-* Thomas Lotze
-* Frank Mittelbach
-* Will Robertson
-* Chris Rowley
-* Rainer Schöpf
-* Joseph Wright
-
-Former members of The LaTeX3 Project team were
-
-* Michael Downes
-* Denys Duchier
-* Alan Jeffrey
-* Martin Schröder
-
-The development team can be contacted
-by e-mail: <latex-team at latex-project.org>; for general LaTeX3 discussion
-the [LaTeX-L list](#Discussion) should be used.
-
------
-
-<p>Copyright (C) 2014-2017 The LaTeX3 Project <br />
-<a href="http://latex-project.org/">http://latex-project.org/</a> <br />
-All rights reserved.</p>
diff --git a/l3build/build-testfiles-plain.lua b/l3build/build-testfiles-plain.lua
deleted file mode 100644
index 1300cd1..0000000
--- a/l3build/build-testfiles-plain.lua
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env texlua
-
--- Testing regression suite for l3build in plain
-
--- Identify the bundle and module
-module = "l3build"
-bundle = ""
-
-maindir = "."
-supportdir  = "."
-testfiledir = "testfiles-plain"
-
-installfiles = {"*.tex", "*.cfg"}
-sourcefiles  = {"*.dtx", "l3build.lua", "*.ins"}
-chkengines   = {"pdftex"}
-
-dofile ("l3build.lua")
diff --git a/l3build/build-testfiles.lua b/l3build/build-testfiles.lua
deleted file mode 100644
index 60d1e2b..0000000
--- a/l3build/build-testfiles.lua
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env texlua
-
--- Testing regression suite for l3build itself
-
--- Identify the bundle and module
-module = "l3build"
-bundle = ""
-
-maindir = "."
-supportdir  = "."
-testfiledir = "testfiles"
-
-installfiles = {"*.tex", "*.cfg"}
-sourcefiles  = {"*.dtx", "l3build.lua", "*.ins"}
-
-dofile ("l3build.lua")
diff --git a/l3build/build.lua b/l3build/build.lua
deleted file mode 100644
index 033ac9c..0000000
--- a/l3build/build.lua
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env texlua
-
--- Build script for LaTeX3 "l3build" files
-
--- Identify the bundle and module
-module = "l3build"
-bundle = ""
-
--- Location of main directory: use Unix-style path separators
-maindir = ".."
-
--- Non-standard settings
-checkdeps    = { }
-cleanfiles   = {"*.pdf", "*.tex", "*.zip"}
-installfiles = {"l3build.lua", "regression-test.tex"}
-sourcefiles  = {"*.dtx", "l3build.lua", "*.ins"}
-unpackdeps   = { }
-versionfiles = {"*.dtx", "*.md", "l3build.lua"}
-
--- Detail how to set the version automatically
-function setversion_update_line(line, date, version)
-  local date = string.gsub(date, "%-", "/")
-  -- .dtx file
-  if string.match(line, "^%% \\date{Released %d%d%d%d/%d%d/%d%d}$") then
-    line = string.gsub(line, "%d%d%d%d/%d%d/%d%d", date)
-  end
-  -- Markdown files
-  if string.match(
-    line, "^Release %d%d%d%d/%d%d/%d%d$"
-  ) then
-    line = "Release " .. date
-  end
-  -- l3build.lua
-  if string.match(line, "^release_date = \"%d%d%d%d/%d%d/%d%d\"$") then
-    line = "release_date = \"" .. date .. "\""
-  end
-  return line
-end
-
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
diff --git a/l3build/l3build.dtx b/l3build/l3build.dtx
deleted file mode 100644
index 1442ca9..0000000
--- a/l3build/l3build.dtx
+++ /dev/null
@@ -1,1625 +0,0 @@
-% \iffalse
-%
-% File l3build.dtx (C) Copyright 2014-2017 The LaTeX3 Project
-%
-% It may be distributed and/or modified under the conditions of the
-% LaTeX Project Public License (LPPL), either version 1.3c of this
-% license or (at your option) any later version.  The latest version
-% of this license is in the file
-%
-%    http://www.latex-project.org/lppl.txt
-%
-% This file is part of the "l3build bundle" (The Work in LPPL)
-% and all files in that bundle must be distributed together.
-%
-% -----------------------------------------------------------------------
-%
-% The development version of the bundle can be found at
-%
-%    https://github.com/latex3/latex3
-%
-% for those people who are interested.
-%
-%<*driver>
-\RequirePackage{expl3}
-\documentclass[full]{l3doc}
-\renewcommand\partname{Part}
-\usepackage{multicol,needspace}
-\makeatletter
-\addtolength\columnsep{1em}
-\renewcommand\columnseprule{0.4pt}
-\def\@starttoc#1{%
-  \begin{multicols}{2}
-  \small
-  \makeatletter
-  \@input{\jobname.#1}%
-  \expandafter\newwrite\csname tf@#1\endcsname
-  \immediate\openout \csname tf@#1\endcsname \jobname.#1\relax
-  \@nobreakfalse
-  \end{multicols}}
-\makeatother
-\newenvironment{buildcmd}[1]{%
-  \bigskip\par\noindent\hspace{-\parindent}%
-  \fbox{\ttfamily \textcolor[gray]{0.5}{\$} texlua build.lua #1}%
-  \nopagebreak\smallskip\nopagebreak\par\nopagebreak\noindent\ignorespaces
- }
- {}
-\makeatletter
-\newcommand\luavar[1]{\@ifundefined{lua_#1}{\ERROR}{\texttt{\@nameuse{lua_#1}}}}
-\newcommand\luavarset[3]{\@namedef{lua_#1}{#2}}
-\newcommand\luavarseparator{}
-\makeatother
-\def\allluavars{
-\luavarset{module}{""}{The name of the module.}
-\luavarset{bundle}{""}{The name of the bundle in which the module belongs.}
-\luavarset{ctanpkg}{bundle}{Name of the bundle on CTAN}
-\luavarseparator
-\luavarset{modules}{\{~\}}{The list of all modules in a bundle (when not auto-detecting)}
-\luavarset{exclmodules}{\{~\}}{Directories to be excluded from automatic module detection}
-\luavarseparator
-\luavarset{maindir}     {"."}{The top level directory for this module or bundle.}
-\luavarset{supportdir}  {maindir .. "/support"}     {Where copies of files to support check/doc compilation are stored.}
-\luavarset{testfiledir} {maindir .. "/testfiles"}   {Where the tests are.}
-\luavarset{testsuppdir} {testfiledir .. "/support"} {Where support files for the tests are.}
-\luavarseparator
-\luavarset{localdir}   {maindir .. "/build/local"}  {Generated folder where support files are placed to allow \enquote{sandboxed} \TeX{} runs.}
-\luavarset{testdir}    {maindir .. "/build/test"}   {Generated folder where tests are run.}
-\luavarset{typesetdir} {maindir .. "/build/doc"}    {Generated folder where typesetting is run.}
-\luavarset{unpackdir}  {maindir .. "/build/unpack"} {Generated folder where unpacking occurs.}
-\luavarset{distribdir} {maindir .. "/build/distrib"}{Generated folder where the archive is created.}
-\luavarset{ctandir}    {distribdir .. "/ctan"}      {Generated folder where files are organised for CTAN.}
-\luavarset{tdsdir}     {distribdir .. "/tds"}       {Generated folder where files are organised for a TDS.}
-\luavarset{tdsroot}    {"latex"}{Root directory of the TDS structure for the bundle/module to be installed into.}
-\luavarseparator
-\luavarset{bibfiles}          {\{"*.bib"\}}{\BibTeX{} database files.}
-\luavarset{binaryfiles}       {\{"*.pdf", "*.zip"\}}
-                              {Files to be added in binary mode to zip files.}
-\luavarset{bstfiles}          {\{"*.bst"\}}{\BibTeX{} style files.}
-\luavarset{checkfiles}        {\{~\}}{Extra files unpacked purely for tests}
-\luavarset{checksuppfiles}    { }{Files needed for performing regression tests.}
-\luavarset{cmdchkfiles}       {\{~\}}{Files need to perform command checking (\cls{l3doc}-based documentation only).}
-\luavarset{cleanfiles}        {\{"*.log", "*.pdf", "*.zip"\}}{Files to delete when cleaning.}
-\luavarset{demofiles}         {\{~\}}{Files which show how to use a module.}
-\luavarset{docfiles}          {\{~\}}{Files which are part of the documentation but should not be typeset.}
-\luavarset{excludefiles}      {\{"*\string~"\}}            {Files to ignore entirely (default for Emacs backup files).}
-\luavarset{installfiles}      {\{"*.sty"\}}         {Files to install to the \TeX{} tree and similar tasks.}
-\luavarset{makeindexfiles}    {\{"*.ist"\}}{MakeIndex files to be included in a TDS-style zip}
-\luavarset{sourcefiles}       {\{"*.dtx", "*.ins"\}}{Files to copy for unpacking.}
-\luavarset{textfiles}         {\{"*.md", "*.txt"\}}{Plain text files to send to CTAN as-is.}
-\luavarset{typesetdemofiles}  {\{~\}}       {Files to typeset before the documentation (as demos), but where the PDF results are not included in the release.}
-\luavarset{typesetfiles}      {\{"*.dtx"\}} {Files to typeset for documentation.}
-\luavarset{typesetsuppfiles}  {\{~\}}       {Files needed to support typesetting when \enquote{sandboxed}.}
-\luavarset{typesetsourcefiles}{\{~\}}       {Files to copy to unpacking when typesetting.}
-\luavarset{unpackfiles}       {\{"*.ins"\}} {Files to run to perform unpacking.}
-\luavarset{unpacksuppfiles}   {\{~\}}       {Files needed to support unpacking when \enquote{sandboxed}.}
-\luavarset{versionfiles}      {\{"*.dtx"\}} {Files for automatic version editing.}
-\luavarseparator
-\luavarset{bakext} {".bak"} {Extension of backup files.}
-\luavarset{dviext} {".dvi"} {Extension of DVI files.}
-\luavarset{lvtext} {".lvt"} {Extension of test files.}
-\luavarset{tlgext} {".tlg"} {Extension of test file output.}
-\luavarset{lvtext} {".lve"} {Extension of auto-generating test file output.}
-\luavarset{logext} {".log"} {Extension of checking output, before processing it into a \texttt{.tlg}.}
-\luavarset{pdfext} {".pdf"} {Extension of PDF file for checking and saving.}
-\luavarset{psext}  {".ps"}  {Extension of PostScript files.}
-\luavarseparator
-\luavarset{checkdeps}   {\{~\}} {List of build unpack dependencies for checking.}
-\luavarset{typesetdeps} {\{~\}} {\dots for typesetting docs.}
-\luavarset{unpackdeps}  {\{~\}} {\dots for unpacking.}
-\luavarseparator
-\luavarset{checkengines}{\{"pdftex", "xetex", "luatex"\}} {Engines to check with \texttt{check} by default.}
-\luavarset{stdengine}    {"pdtex"} {Engine to generate \texttt{.tlg} file from.}
-\luavarset{checkformat}  {"latex"} {Format to use for tests.}
-\luavarseparator
-\luavarset{typesetexe} {"pdflatex"} {Executable for compiling \texttt{doc(s)}.}
-\luavarset{unpackexe}  {"tex"}      {Executable for running \texttt{unpack}.}
-\luavarset{zipexe}     {"zip"}      {Executable for creating archive with \texttt{ctan}.}
-\luavarseparator
-\luavarset{checkopts}  {"-interaction=nonstopmode"}{Options based to engine when running checks.}
-\luavarset{cmdchkopts} {"-interaction=batchmode"}  {Options based to engine when running command checks.}
-\luavarset{typesetopts}{"-interaction=nonstopmode"}{Options based to engine when typesetting.}
-\luavarset{unpackopts} {""}                        {Options based to engine when unpacking.}
-\luavarset{zipopts}    {"-v -r -X"}                {Options based to zip program.}
-\luavarseparator
-\luavarset{checksearch}  {true}  {Look in \texttt{tds} dirs for checking?}
-\luavarset{typesetsearch}{true}  {Look in \texttt{tds} dirs for typesetting docs?}
-\luavarset{unpacksearch} {true}  {Look in \texttt{tds} dirs for unpacking?}
-\luavarseparator
-\luavarset{glossarystyle}{"gglo.ist"}{MakeIndex style file for glossary/changes creation}
-\luavarset{indexstyle}   {"gind.ist"}{MakeIndex style for index creation}
-\luavarseparator
-\luavarseparator
-\luavarset{biberexe}     {"biber"}    {Biber executable}
-\luavarset{biberopts}    {""}         {Biber options}
-\luavarset{bibtexexe}    {"bibtex8"}  {\BibTeX{} executable}
-\luavarset{bibtexopts}   {"-W"}       {\BibTeX{} options}
-\luavarset{makeindexexe} {"makeindex"}{MakeIndex executable}
-\luavarset{makeindexopts}{""}         {MakeIndex options}
-\luavarseparator
-\luavarset{asciiengines}{\{"pdftex"\}}{Engines which should log as sure ASCII}
-\luavarset{checkruns}   {1}           {How many times to run a check file before comparing the log.}
-\luavarset{epoch}       {1463734800}  {Epoch (Unix date) to set for test runs.}
-\luavarset{maxprintline}{79}          {Length of line to use in log files.}
-\luavarset{packtdszip}  {false}       {Build a TDS-style zip file for CTAN?}
-\luavarset{scriptname}  {"build.lua"} {Name of script used in dependencies.}
-\luavarset{typesetcmds} {""}          {Instructions to be passed to \TeX{} when doing typesetting.}
-\luavarset{versionform} {""}          {Nature of version strings for auto-replacement.}
-}
-\allluavars
-\newcommand\luavartypeset{%
-  \begingroup
-  \frenchspacing
-  \renewcommand\luavarset[3]{
-    \texttt{##1} & \texttt{##2} & ##3 \\
-  }
-  \renewcommand\luavarseparator{\midrule}
-  \setlength\LTleft{-0.21\linewidth}
-  \begin{longtable}{@{}%
-    >{\small}
-    p{0.18\linewidth}
-    @{\hspace{0.03\linewidth}}
-    >{\footnotesize\hangindent=1em}
-    p{0.34\linewidth}
-    @{\hspace{0.03\linewidth}}
-    >{\small\raggedright\arraybackslash}
-    p{0.63\linewidth}
-    @{}}
-  \toprule
-  Variable & Default & Description \\
-  \midrule\endhead
-  \allluavars
-  \bottomrule
-  \end{longtable}
-  \endgroup
-}
-\newcommand\code{\texttt}
-\newcommand\var{\texttt}
-\usepackage[procnames]{listings}
-\lstset{
-    basicstyle=\ttfamily\small,
-    numbers=left,
-    numberstyle={\tiny\color[gray]{0.4}},
-}
-\usepackage{shortvrb}
-\usepackage{enumitem}
-\usepackage{longtable}
-\MakeShortVerb\|
-\begin{document}
-  \DocInput{\jobname.dtx}
-\end{document}
-%</driver>
-% \fi
-%
-% \title{^^A
-%   The \pkg{l3build} package\\ Checking and building packages^^A
-% }
-%
-% \author{^^A
-%  The \LaTeX3 Project\thanks
-%    {^^A
-%      E-mail:
-%        \href{mailto:latex-team at latex-project.org}
-%          {latex-team at latex-project.org}^^A
-%    }^^A
-% }
-%
-% \date{Released 2017/05/29}
-%
-% \maketitle
-% \tableofcontents
-%
-% \begin{documentation}
-%
-% \section{The \pkg{l3build} system}
-%
-% \subsection{Introduction}
-%
-% The \pkg{l3build} system is a Lua script for building \TeX{} packages, with particular emphasis on regression testing.
-% It is written in cross-platform Lua code, so can be used by any modern \TeX{} distribution with the |texlua| interpreter.
-% A package for building with \pkg{l3build} can be written in any \TeX\ dialect; its defaults are set up for \LaTeX\ packages written in the DocStrip style. (Caveat: minimal testing has yet been performed for non-\LaTeX{} packages.)
-%
-% Test files are written as standalone \TeX{} documents using the |regression-test.tex| setup file; documentation on writing these tests is discussed in Section~\ref{sec:writing-tests}.
-%
-% The |l3build.lua| script is not designed to be executed directly; each package will define its own |build.lua| script as a driver file which both sets variables (such as the name of the package) and then calls the main |l3build.lua| script internally.
-%
-% \pagebreak[2]
-% A standard package layout might look something like the following:
-% \begin{Verbatim}[fontsize=\small]
-%  abc/
-%      abc.dtx
-%      abc.ins
-%      build.lua
-%      README.md
-%      support/
-%      testfiles/
-% \end{Verbatim}
-% Most of this should look fairly self-explanatory.
-% The top level |support/| directory (optional) would contain any necessary files for compiling documentation, running regression tests, and so on.
-%
-% The \pkg{l3build} system is also capable of building and checking \emph{bundles} of packages.
-% To avoid confusion, we refer to either a standalone package or a package within a bundle as a \emph{module}.
-%
-% For example, within the \LaTeX3 project we have the \textsf{l3packages} bundle which contains the \textsf{xparse}, \textsf{xtemplate}, etc., modules.
-% These are all built and distributed as one bundle for installation, distribution \emph{via} CTAN and so forth.
-%
-% Each module in a bundle will have its own build script, and a bundle build script brings them all together.
-% A standard bundle layout would contain the following structure.
-% \begin{Verbatim}
-% mybundle/
-%          build.lua
-%          support/
-%          yyy/                    zoo/
-%              build.lua               build.lua
-%              README.md               README.md
-%              testfiles/              testfiles/
-%              yyy.dtx                 zoo.dtx
-%              yyy.ins                 zoo.ins
-% \end{Verbatim}
-% All modules within a bundle must use the same build script name.
-%
-% In a small number of cases, the name used by CTAN for a module or bundle is
-% different from that used in the installation tree. For example, the \LaTeXe{}
-% kernel is called \pkg{latex-base} by CTAN but is located inside
-% \texttt{\meta{texmf}/tex/latex/base}. This can be handled by using
-% \var{ctanpkg} for the name required by CTAN to override the standard
-% value.
-%
-% The |testfiles/| folder is local to each module, and its layout consists of a series of regression tests with their outputs.
-% \begin{Verbatim}
-% testfiles/
-%           test1.lvt
-%           test1.tlg
-%           ...
-%           support/
-%                   my-test.cls
-% \end{Verbatim}
-% Again, the |support/| directory contains any files necessary to run some or all of these tests.
-%
-% When the build system runs, it creates a directory |build/| for various unpacking, compilation, and testing purposes.
-% For a module, this build folder can be in the main directory of the package itself, but for a bundle it should be common for the bundle itself and for all modules within that bundle.
-% A |build/| folder can be safety deleted; all material within is re-generated for each command of the \pkg{l3build} system.
-%
-% \subsection{Main build commands}
-%
-% In the working directory of a bundle or module, the following commands can be executed:
-% \begin{itemize}[noitemsep]\ttfamily
-% \item check
-% \item check \meta{name(s)}
-% \item cmdcheck
-% \item clean
-% \item doc \meta{name(s)}
-% \item install
-% \item save \meta{name(s)}
-% \item setversion
-% \end{itemize}
-% These commands are described below.
-%
-% As well as these commands, the system recognises the options
-% \begin{itemize}
-% \item \texttt{--date} (\texttt{-d}) Date to use when setting version
-%   data
-% \item \texttt{--engine} (\texttt{-e}) Sets the engine to use for
-%   testing
-% \item \texttt{--halt-on-error} (\texttt{-H}) Specifies that checks
-%   should stop as soon as possible, rather than running all requested
-%   tests; the difference file is printed in the terminal directly in the case of failure
-% \item \texttt{--pdf} (\texttt{-p}) Test PDF file against a reference
-%   version rather than using a log comparison
-% \item \texttt{--quiet} (\texttt{-q}) Suppresses output from unpacking
-% \item \texttt{--release} (\texttt{-r}) Release string to use when setting
-%   version data
-% \item \texttt{--textfiledir} (\texttt{-t}) Select a specific set of tests
-% \end{itemize}
-%
-% \begin{buildcmd}{check}
-% The |check| command runs the entire test suite.
-% This involves iterating through each \texttt{.lvt} file in the test directory (specified by the \var{testfiledir} variable), compiling each test in a \enquote{sandbox} (a directory specified by \var{testdir}), and comparing the output against each matching predefined \texttt{.tlg} file.
-%
-% If changes to the package or the typesetting environment have affected the results, the check for that file fails.
-% A |diff| of the expected to actual output should then be inspected to determine the cause of the error; it is located in the \var{testdir} directory (default \luavar{testdir}).
-%
-% On Windows, the |diff| program is not available and so |fc| is used instead
-% (generating an |.fc| file). Setting the environmental variables |diffexe|
-% and |diffext| can be used to adjust the choice of comparison made: the standard
-% values are
-% \begin{itemize}
-%   \item[Windows] |diffext = fc|, |diffexe = fc /n|
-%   \item[*nix] |diffext = diff|, |diffexe = diff -c --strip-trailing-cr|
-% \end{itemize}
-%
-% The following files are moved into the \enquote{sandbox} for the |check| process:
-% \begin{itemize}
-% \item all \var{installfiles} after unpacking;
-% \item all \var{checkfiles} after unpacking;
-% \item any files in the directory \var{testsuppdir};
-% \item any files that match \var{checksuppfiles} in the \var{supportdir}.
-% \end{itemize}
-% This range of possibilities allow sensible defaults but significant flexibility for defining your own test setups.
-%
-% Checking can be performed with any or all of the `engines' \texttt{pdftex}, \texttt{xetex}, and \texttt{luatex}.
-% By default, each test is executed with all three, being compared against the \texttt{.tlg} file produced from the \var{pdftex} engine (these defaults are controlled by the |checkengines| and |stdengine| variable respectively).
-% The format used for tests can be altered by setting \var{checkformat}: the default setting \texttt{latex} means that tests are run using \emph{e.g.}~\texttt{pdflatex}, whereas setting to \texttt{plain} will run tests using \emph{e.g.}~\texttt{pdftex}.
-% (Currently, this should be one of \texttt{latex} or \texttt{plain}.)
-% To perform the check, the engine typesets each test \var{checkruns} times.
-% More detail on this in the documentation on |save|.
-% Options passed to the binary are defined in the variable \var{checkopts}.
-%
-% By default, |texmf| trees are searched for input files when checking. This can be disabled by setting \var{checksearch} to |false|: isolation provides confidence that the tests cannot accidentally be running with incorrect files installed in the main distribution or |hometexmf|.
-% \end{buildcmd}
-%
-%
-% \begin{buildcmd}{check \meta{name(s)}}
-% Checks only the test \texttt{\meta{name(s)}.lvt}.
-% All engines specified by \var{checkengines} are tested unless the command
-% line option \texttt{--engine} (or \texttt{-e}) has been given to limit
-% testing to a single engine.
-% \end{buildcmd}
-%
-% \begin{buildcmd}{check -p}
-% Rather than the log-based checking carried out by the standard
-% |check| target, running with the |-p| option carries out a binary
-% comparison of the PDF files produced by typesetting against those
-% saved in \var{testfiledir}.
-%
-% This functionality requires \TeX{} Live 2016 or later as it needs support
-% from the engines not available in earlier releases.
-% \end{buildcmd}
-%
-% \begin{buildcmd}{cmdcheck}
-% For \cls{l3doc}-based sources, allows checking that the commands defined in the code part  (by \var{cmdchkfiles}) are documented in the description part.
-% This is performed by passing the |check| option to the \cls{l3doc} class, typesetting the file(s) to check with engine \var{stdengine} with options \var{cmdchkopts}, and checking the resultant |.cmds| file(s).
-% Dependencies are specified also with \var{checkdeps}.
-% \end{buildcmd}
-%
-%
-% \begin{buildcmd}{clean}
-% This command removes all temporary files used for package bundling and regression testing.
-% In the standard layout, these are all files within the directories defined by \var{localdir}, \var{testdir}, \var{typesetdir} and \var{unpackdir}, as well as all files defined in the \var{cleanfiles} variable in the same directory as the script.
-% The defaults are |.pdf| files from typesetting (|doc|) and |.zip| files from bundling (|ctan|).
-% \end{buildcmd}
-%
-%
-% \begin{buildcmd}{ctan}
-% Creates an archive of the package and its documentation, suitable for uploading to CTAN
-% The archive is compiled in \var{distribdir}, and if the results are successful the resultant |.zip| file is moved into the same directory as the build script.
-% If \var{packtdszip} is set true then  the building process includes a |.tds.zip| file containing the `\TeX\ Directory Structure' layout of the package or bundle.
-% The archive therefore may contain two `views' of the package:
-% \begin{Verbatim}
-% abc.zip/
-%         abc/
-%             abc.dtx
-%             abc.ins
-%             abc.pdf
-%             README.md
-%         abc.tds.zip/
-%                     doc/latex/abc/
-%                                   abc.pdf
-%                                   README.md
-%                  source/latex/abc/
-%                                   abc.dtx
-%                                   abc.ins
-%                     tex/latex/abc/
-%                                   abc.sty
-% \end{Verbatim}
-% The files copied into the archive are controlled by a number of variables.
-% The `root' of the TDS structure is defined by \var{tdsroot}, which is \luavar{tdsroot} by default. Plain users would redefine this to |"plain"| (or perhaps |"generic"|), for example.
-% The build process for a |.tds.zip| file currently assumes a `standard'
-% structure in which all extracted files should be placed inside the |tex|
-% tree in a single directory, as shown above. If the module includes any
-% \BibTeX{} or MakeIndex styles these will be placed in the appropriate
-% subtrees.
-%
-% \pagebreak[2]
-% The |doc| tree is constructed from:
-% \begin{itemize}
-% \item all files matched by \var{demofiles},
-% \item all files matched by \var{docfiles},
-% \item all files matched by \var{typesetfiles} with their extension replaced with |.pdf|,
-% \item all files matched by \var{textfiles},
-% \item all files matched by \var{bibfiles}.
-% \end{itemize}
-% The |source| tree is constructed from all files matched by \var{typesetfiles} and \var{sourcefiles}.
-% The |tex| tree from all files matched by \var{installfiles}.
-%
-% Files that should always be excluded from the archive are matched against the \var{excludefiles} variable; by default this is \luavar{excludefiles}, which match Emacs' autosave files.
-%
-% Binary files should be specified with the \var{binaryfiles} variable (default \luavar{binaryfiles}); these are added to the zip archive without normalising line endings (text files are automatically converted to Unix-style line endings).
-%
-% To create the archive, by default the binary \var{zipexe} is used (\luavar{zipexe}) with options \var{zipopts} (|-v -r -X|). The intermediate build directories \var{ctandir} and \var{tdsdir} are used to construct the archive.
-% \end{buildcmd}
-%
-%
-% \begin{buildcmd}{doc}
-% Compiles documentation files in the \var{typesetdir} directory.
-% In the absence of one or more file names, all documentation is typeset;
-% a file list may be given at the command line for selective typesetting.
-% If the compilation is successful the |.pdf| is moved back into the main directory.
-%
-% The documentation compilation is performed with the \var{typesetexe} binary (default \texttt{pdflatex}), with options \var{typesetopts}.
-% Additional \TeX{} material defined in \var{typesetcmds} is passed to the document (e.g., for writing |\\PassOptionsToClass{l3doc}{letterpaper}|, and so on---note that backslashes need to be escaped in Lua strings).
-%
-% Files that match |typesetsuppfiles| in the |support| directory (|supportdir|) are copied into the |build/local| directory (|localdir|) for the typesetting compilation process.
-% Additional dependencies listed in the \var{typesetdeps} variable (empty by default) will also be installed.
-%
-% Source files specified in \var{sourcefiles} and \var{typesetsourcefiles}
-% are unpacked before the typesetting takes place. (In most cases
-% \var{typesetsourcefiles} will be mepty, but may be used where there are
-% files to unpack \emph{only} for typesetting.)
-%
-% If \var{typesetsearch} is \code{true} (default), standard \texttt{texmf} search trees are used in the typesetting compilation. If set to false, \emph{all} necessary files for compilation must be included in the |build/local| sandbox.
-%
-% \end{buildcmd}
-%
-% \begin{buildcmd}{doc \meta{name(s)}}
-%   Typesets only the files with the \meta{name(s)} given, which should be the
-%   root name without any extension.
-% \end{buildcmd}
-%
-% \begin{buildcmd}{install}
-% Copies all package files (defined by \var{installfiles}) into the user's home \texttt{texmf} tree in the form of the \TeX\ Directory Structure.
-% \end{buildcmd}
-%
-% \begin{buildcmd}{save \meta{name(s)}}
-% This command runs through the same execution as |check| for a specific test(s) \texttt{\meta{name(s)}.lvt}.
-% This command saves the output of the test to a |.tlg| file.
-% This file is then used in all subsequent checks against the \texttt{\meta{name}.lvt} test.
-%
-% If the \texttt{--engine} (or \texttt{-e}) is specified (one of |pdftex|, |xetex|, or |luatex|), the saved output is stored in \texttt{\meta{name}.\meta{engine}.tlg}. This is necessary if running the test through a different engine produces a different output.
-% A normalisation process is performed when checking to avoid common differences such as register allocation; full details are listed in section~\ref{sec:norm}.
-% \end{buildcmd}
-%
-% \begin{buildcmd}{save -p \meta{name(s)}}
-% This version of |save| will store the PDF files produced from
-% \texttt{\meta{name(s)}.lvt} in addition to the |.tlg| file, and thus allows
-% binary comparison of the result of typesetting.
-%
-% This functionality requires \TeX{} Live 2016 or later as it needs support
-% from the engines not available in earlier releases.
-% \end{buildcmd}
-%
-% \begin{buildcmd}{setversion}
-% Modifies the content of files specified by |versionfiles| to allow
-% automatic updating of the file date and version. The latter are
-% specified using the |-d| and |-r| command line options and if not
-% given will default to the current date in ISO format (YYYY-MM-DD) and |-1|,
-% respectively. As detailed below, the standard set up has no search pattern
-% defined for this target and so no action will be taken \emph{unless}
-% a version type for substitution is set up (using \var{versionform} or
-% by defining a custom function).
-% \end{buildcmd}
-%
-% \begin{buildcmd}{unpack}
-% This is an internal target that is normally not needed on user level.
-% It unpacks all files into the directory defined by \var{unpackdir}. This occurs before other build commands such as |doc|, |check|, etc.
-%
-% The unpacking process is performed by executing the \var{unpackexe} (default \texttt{tex}) with options \var{unpackopts} on all files defined by the \var{unpackfiles} variable; by default, all files that match \luavar{unpackfiles}.
-%
-% If additional support files are required for the unpacking process, these can be enumerated in the \var{unpacksuppfiles} variable.
-% Dependencies for unpacking are defined with \var{unpackdeps}.
-%
-% By default this process allows files to be accessed in all standard |texmf| trees; this can be disabled by setting \var{unpacksearch} to |false|.
-% \end{buildcmd}
-%
-% \subsection{Example build scripts}
-%
-% An example of a standalone build script for a package that uses self-contained |.dtx| files is shown in Figure~\ref{fig:breqn}.
-% Here, the |module| only is defined, and since it doesn't use |.ins| files so the variable \var{unpackfiles} is redefined to run |tex| on the |.dtx| files instead to generate the necessary |.sty| files.
-% There are some PDFs in the repository that shouldn't be part of a CTAN submission, so they're explicitly excluded, and here unpacking is done `quietly' to minimise console output when building the package.
-% Finally, because this is a standalone package, we assume that \pkg{l3build} is installed in the main \TeX{} distribution and find the Lua script by searching for it.
-%
-% \begin{figure}[!b]
-%   \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6]
-%     #!/usr/bin/env texlua
-%
-%     -- Build script for breqn
-%
-%     module = "breqn"
-%
-%     unpackfiles = {"*.dtx"}
-%     excludefiles = {"*/breqn-abbr-test.pdf",
-%                     "*/eqbreaks.pdf"}
-%     unpackopts  = "-interaction=batchmode"
-%
-%     kpse.set_program_name("kpsewhich")
-%     dofile(kpse.lookup("l3build.lua"))
-%   \end{lstlisting}
-% \caption{The build script for the \pkg{breqn} package.}
-% \label{fig:breqn}
-% \end{figure}
-%
-% An example of a bundle build script for \pkg{l3packages} is shown in Figure~\ref{fig:bundle}.
-% Note for \LaTeX3 we use a common file to set all build variables in one place, and the path to the |l3build.lua| script is hard-coded so we always use our own most recent version of the script.
-% An example of an accompanying module build script is shown in Figure~\ref{fig:module}.
-%
-% \begin{figure}[p]
-%   \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6]
-%     #!/usr/bin/env texlua
-%
-%     -- Build script for LaTeX3 "l3packages" files
-%
-%     -- Identify the bundle: there is no module as this is the "driver"
-%     bundle = "l3packages"
-%
-%     -- Location of main directory: use Unix-style path separators
-%     maindir = ".."
-%
-%     -- Load the common build code: this is the one place that a path
-%     -- needs to be hard-coded
-%     dofile (maindir .. "/l3build/l3build-config.lua")
-%     dofile (maindir .. "/l3build/l3build.lua")
-%   \end{lstlisting}
-% \caption{The build script for the \pkg{l3packages} bundle.}
-% \label{fig:bundle}
-% \end{figure}
-%
-% \begin{figure}[p]
-%   \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6]
-%     #!/usr/bin/env texlua
-%
-%     -- Build script for LaTeX3 "xparse" files
-%
-%     -- Identify the bundle and module:
-%     bundle = "l3packages"
-%     module = "xparse"
-%
-%     -- Location of main directory: use Unix-style path separators
-%     -- Should match that defined by the bundle.
-%     maindir = "../.."
-%
-%     -- Load the common build code: this is the one place that a path
-%     -- needs to be hard-coded
-%     dofile (maindir .. "/l3build/l3build-config.lua")
-%     dofile (maindir .. "/l3build/l3build.lua")
-%   \end{lstlisting}
-% \caption{The build script for the \pkg{xparse} module.}
-% \label{fig:module}
-% \end{figure}
-%
-% \begin{figure}[p]
-%   \begin{lstlisting}[frame=single,gobble = 6]
-%     @echo off
-%     texlua build.lua %*
-%   \end{lstlisting}
-% \caption{Windows batch file wrapper for running the build process.}
-% \label{fig:batch}
-% \end{figure}
-%
-% Under a Unix-like platform, you may wish to run `|chmod +x build.lua|' on these files, which allows a simpler command line use. Instead of writing\\
-% \hspace*{2\parindent}|texlua build.lua check|\\ for example, you would simply write\\
-% \hspace*{2\parindent}|./build.lua check|\\
-% instead. (Or even omit the |./| depending on your path settings.)
-% Windows users can achieve a similar effect by creating a file |build.bat| as show in Figure~\ref{fig:batch}.
-%
-% \subsection{Variables}
-%
-% This section lists all variables defined in the |l3build.lua| script that are available for customisation.
-%
-% \luavartypeset
-%
-% \subsection{Multiple sets of tests}
-%
-% In most cases, a single set of tests will be appropriate for the module, with
-% a common set of configuration settings applying. However, there are situations
-% where you may need entirely independent sets of tests which have different
-% setting values, for example using different formats or where the entire set
-% will be engine-dependent. To support this, \pkg{l3build} offers the |--testfiledir|
-% (|-t|) command line option. When this is given with a directory argument it
-% overrides the \var{testfiledir} variable. Moreover, before the tests are run,
-% \pkg{l3build} will read |config.lua| within the directory (if available). This
-% should comprise a list of settings which apply to the tests in place of those in
-% the main build script.
-%
-% For example, for the core \LaTeXe{} tests the main test files are contained
-% in a directory |testfiles| and have \var{checksearch} set \var{false}. To test
-% font loading for \XeTeX{} and \LuaTeX{} there are a second set of tests in
-% |testfiles-TU| which use the short |config.lua| file shown in
-% Figure~\ref{fig:testfiledir}. These additional tests are then run using
-% |texlua build.lua check --testfiledir=testfiles-TU|.
-% \begin{figure}
-%   \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6]
-%     -- Special config for these tests
-%     checksearch  = true
-%     checkengines = {"xetex","luatex"}
-%   \end{lstlisting}
-% \caption{The build script for the \pkg{xparse} module.}
-% \label{fig:testfiledir}
-% \end{figure}
-%
-% \subsection{Dependencies}
-%
-% If you have multiple packages that are developed separately but still interact in some way, it's often desirable to integrate them when performing regression tests.
-% For \LaTeX3, for example, when we make changes to \pkg{l3kernel} it's important to check that the tests for \pkg{l3packages} still run correctly, so it's necessary to include the \pkg{l3kernel} files in the build process for \pkg{l3packages}.
-%
-% In other words, \pkg{l3packages} is \emph{dependent} on \pkg{l3kernel}, and this is specified in \pkg{l3build} by setting appropriately the variables \texttt{checkdeps}, \texttt{typesetdeps}, and \texttt{unpackdeps}.
-% The relevant parts of the \LaTeX3 repository is structured as the following.
-% \Needspace{3\baselineskip}
-% \begin{Verbatim}
-% l3/
-%    l3kernel/
-%               build.lua
-%               expl3.dtx
-%               expl3.ins
-%               ...
-%               testfiles/
-%    l3packages/
-%               build.lua
-%               xparse/
-%                      build.lua
-%                      testfiles/
-%                      xparse.dtx
-%                      xparse.ins
-%    support/
-% \end{Verbatim}
-% For \LaTeX3 build files, |maindir| is defined as top level folder |l3|, so all support files are located here, and the build directories will be created there.
-% To set \pkg{l3kernel} as a dependency of \pkg{l3package}, within |l3packages/xparse/build.lua| the equivalent of the following is set:
-% \begin{Verbatim}
-%   maindir = "../.."
-%   checkdeps = {maindir .. "/l3kernel"}
-% \end{Verbatim}
-% This ensures that the \pkg{l3kernel} code is included in all processes involved in unpacking and checking and so on.
-% The name of the script file in the dependency is set with the |scriptname| variable; by default these are |"build.lua"|.
-%
-%
-% \subsection{Output normalisation}
-% \label{sec:norm}
-%
-% To allow test files to be used between different systems (\emph{e.g.}~when
-% multiple developers are involved in a project), the log files are normalised
-% before comparison during checking. This removes some system-dependent
-% data but also some variations due to different engines. This normalisation
-% consists of two parts: removing (\enquote{ignoring}) some lines and modifying
-% others to give consistent test. Currently, the following types of line are
-% ignored:
-% \begin{itemize}
-%   \item Lines before the \cs{START}, after the \cs{END} and within
-%     \cs{OMIT}/\cs{TIMO} blocks
-%   \item Entirely blank lines, including those consisting only of spaces.
-%   \item Lines containing file dates in format
-%    \texttt{\meta{yyyy}/\meta{mm}/\meta{dd}}.
-%  \item Lines starting \cs{openin} or \cs{openout}.
-% \end{itemize}
-% Modifications made in lines are:
-% \begin{itemize}
-%   \item Removal spaces at the start of lines.
-%   \item Removal of |./| at start of file names.
-%   \item Standardisation of the list of units known to \TeX{} (\pdfTeX{}
-%     and \LuaTeX{} add a small number of additional units which are not
-%     known to \TeX90 or \XeTeX{}).
-%   \item Standardisation of \verb*|\csname\endcsname | to |\csname\endcsname|
-%     (the former is formally correct, but the latter was produced for many
-%     years due to a \TeX{} bug).
-%   \item Conversion of \texttt{on line \meta{number}} to \texttt{on line ...}
-%     to allow flexibility in changes to test files.
-% \end{itemize}
-%
-% \LuaTeX{} makes several additional changes to the log file. As normalising
-% these may not be desirable in all cases, they are handled separately.
-% When creating \LuaTeX{}-specific test files (either with \LuaTeX{} as
-% the standard engine or saving a \LuaTeX{}-specific |.tlg| file) no further
-% normalisation is undertaken. On the other hand, for cross-engine comparison
-% the following normalisation is applied:
-% \begin{itemize}
-%   \item Removal of additional (unused) |\discretionary| points.
-%   \item Normalisation of some |\discretionary| data to a \TeX{}90 form.
-%   \item Removal of |U+...| notation for missing characters.
-%   \item Removal of |display| for display math boxes
-%     (included by \TeX90/\pdfTeX{}/\XeTeX).
-%   \item Removal of Omega-like |direction TLT| information.
-%   \item Removal of additional whatsit containing local paragraph information
-%     (|\localinterlinepenalty|, \emph{etc.}).
-%   \item Rounding of glue set to four decimal places (glue set may be
-%     slightly different in \LuaTeX{} compared to other engines).
-%   \item Conversion of low chars ($0$ to $31$) to |^^| notation.
-% \end{itemize}
-%
-% When making comparisons between 8-bit and Unicode engines it is useful to
-% format the top half of the 8-bit range such that it appears in the log as
-% |^^|\texttt{\meta{char}} (the exact nature of the 8-bit output is otherwise
-% dependent on the active code page). This may be controlled using the
-% |asciiengines| option. Any engines named here will use a |.tcx| file to
-% produce only ASCII chars in the log output, whilst for other engines
-% normalisation is carried out from UTF-8 to ASCII. If the option is set to
-% an empty table the latter process is skipped: suitable for cases where only
-% Unicode engines are in use.
-%
-% \section{Writing test files}
-% \label{sec:writing-tests}
-%
-% Test files are written in a \TeX{} dialect using the support file |regression-test.tex|, which should be |\input| at the very beginning of each test.
-% Additional customisations to this driver can be included in a local |regression-test.cfg| file, which will be loaded automatically if found.
-%
-% The macros loaded by |regression-test.tex| set up the test system and provide a number of commands to aid the production of a structured test suite.
-% The basis of the test suite is to output material into the |.log| file, from which a normalised test output (|.tlg|) file is produced by the build command |save|.
-% A number of commands are provided for this; they are all written in uppercase to help avoid possible conflicts with other package commands.
-%
-% \subsection{Metadata and structural commands}
-%
-% Any commands that write content to the |.log| file that should be ignored can be surrounded by |\OMIT| \dots\ |\TIMO|.
-% At the appropriate location in the document where the |.log| comparisons should start (say, after |\begin{document}|), the test suite must contain the |\START| macro.
-% The test should then include \cs{AUTHOR}\marg{authors details} in case a test file fails in the future and needs to be re-analysed.
-%
-% Some additional diagnostic information can then be included as metadata for the conditions of the test.
-% The desired format can be indicated with \cs{FORMAT}\marg{format name}, and any packages or classes loaded can be indicated with
-%
-% \noindent\hspace*{2\parindent} \cs{CLASS}\oarg{options}\marg{class name, version}\par
-% \noindent\hspace*{2\parindent} \cs{PACKAGE}\oarg{options}\marg{package name, version}
-%
-% \noindent These do not provide information that is useful for automated checking; after all, packages change their version numbers frequently.
-% Rather, including this information in a test indicates the conditions under which the test was definitely known to pass at a certain time in the past.
-%
-% The |\END| command signals the end of the test (but read on).
-% Some additional diagnostic information is printed at this time to debug if the test did not complete `properly' in terms of mismatched brace groups or \cs{if}\dots\cs{fi} groups.
-%
-% In a \LaTeX{} document, |\end{document}| will implicitly call |\END| at the very end of the  compilation process.
-% If |\END| is used directly (replacing |\end{document}| in the test), the compilation will halt almost immediately, and various tasks that |\end{document}| usually performs will not occur (such as potentially writing to the various |.toc| files, and so on). This can be an advantage if there is additional material printed to the log file in this stage that you wish to ignore, but it is a disadvantage if the test relies on various auxiliary data for a subsequent typesetting run.
-% (See the \var{checkruns} variable for how these tests would be test up.)
-%
-% \subsection{Commands to help write tests}
-%
-% A simple command \cs{CHECKCOMMAND}\cs{\meta{macro}} is provided to check whether a particular \cs{\meta{macro}} is defined, undefined, or equivalent to \cs{relax}.
-% This is useful to flag either that internal macros are remaining local to their definitions, or that defined commands definitely are defined, or even as a reminder that commands you intend to define in a future package need to be tested once they appear.
-%
-% \cs{TYPE} is used to write material to the \texttt{.log} file, like \LaTeX's \cs{typeout}, but it allows `long' input.
-% The following commands are defined to use \cs{TYPE} to output strings to the \texttt{.log} file.
-% \begin{itemize}
-% \item
-% \cs{SEPARATOR} inserts a long line of \texttt{=} symbols to break up the log output.
-% \item
-% \cs{NEWLINE} inserts a linebreak into the log file.
-% \item
-% \cs{TRUE}, \cs{FALSE}, \cs{YES}, \cs{NO} output those strings to the log file.
-% \item
-% \cs{ERROR} is \emph{not} defined but is commonly used to indicate a code path that should never be reached.
-% \item
-% The \cs{TEST}\marg{title}\marg{contents} command surrounds its \meta{contents} with some \cs{SEPARATOR}s and a \meta{title}.
-% \item
-% \cs{TESTEXP} surrounds its contents with \cs{TYPE} and formatting to match \cs{TEST}; this can be used as a shorthand to test expandable commands.
-% \item
-% TODO: would a \cs{TESTFEXP} command (based on \cs{romannumeral} expansion) be useful as well?
-% \end{itemize}
-% An example of some of these commands is shown following.
-% \begin{Verbatim}
-% \TEST{bool_set,~lazy~evaluation}
-%  {
-%   \bool_set:Nn \l_tmpa_bool
-%    {
-%     \int_compare_p:nNn 1=1
-%     && \bool_lazy_any_p:n
-%      {
-%        { \int_compare_p:nNn 2=3 }
-%        { \int_compare_p:nNn 4=4 }
-%        { \int_compare_p:nNn 1=\ERROR } % is skipped
-%      }
-%     && \int_compare_p:nNn 2=2
-%    }
-%   \bool_if:NTF \l_tmpa_bool \TRUE \FALSE
-%  }
-% \end{Verbatim}
-% This test will produce the following in the output.
-% \begin{Verbatim}
-% ==========================================
-% TEST 8: bool_set, lazy evaluation
-% ==========================================
-% TRUE
-% ==========================================
-% \end{Verbatim}
-% (Only if it's the eighth test in the file of course, and assuming \pkg{expl3}
-% coding conventions are active.)
-%
-% \subsection{Showing box content}
-%
-% The commands introduced above are only useful for checking algorithmic or logical correctness.
-% Many packages should be tested based on their typeset output instead; \TeX{} provides a mechanism for this by printing the contents of a box to the log file.
-% The |regression-test.tex| driver file sets up the relevant \TeX{} parameters to produce as much output as possible when showing box output.
-%
-% A plain \TeX{} example of showing box content follows.
-% \begin{Verbatim}[frame=single,fontsize=\small]
-% \input regression-test.tex\relax
-% \START
-% \setbox0=\hbox{\rm hello \it world $a=b+c$}
-% \showbox0
-% \END
-% \end{Verbatim}
-% This produces the output shown in Figure~\ref{fig:box-log} (left side).
-% It is clear that if the definitions used to typeset the material in the box changes, the log output will differ and the test will no longer pass.
-%
-% The equivalent test in \LaTeXe{} using \pkg{expl3} is similar.
-% \begin{Verbatim}[frame=single,fontsize=\small]
-% \input{regression-test.tex}
-% \documentclass{article}
-% \usepackage{expl3}
-% \START
-% \ExplSyntaxOn
-% \box_new:N \l_tmp_box
-% \hbox_set:Nn \l_tmp_box {hello~ \emph{world}~ $a=b+c$}
-% \box_show:N \l_tmp_box
-% \ExplSyntaxOff
-% \END
-% \end{Verbatim}
-% The output from this test is shown in Figure~\ref{fig:box-log} (right side).
-% There is marginal difference (mostly related to font selection and different logging settings in \LaTeX) between the plain and \pkg{expl3} versions.
-%
-% When examples are not self-contained enough to be typeset into boxes, it is possible to ask \TeX{} to output the entire contents of a page.
-% Insert \cs{showoutput} for \LaTeX{} or set \cs{tracingoutput} positive for plain \TeX{}; ensure that the test ends with \cs{newpage} or equivalent because \TeX{} waits until the entire page is finished before outputting it.
-%
-% TODO: should we add something like \cs{TRACEPAGES} to be format-agnostic here? Should this perhaps even be active by default?
-%
-% \begin{figure}
-% \hspace*{-3cm}
-%   \begin{BVerbatim}[fontsize=\small]
-% > \box0=
-% \hbox(6.94444+0.83333)x90.56589
-% .\tenrm h
-% .\tenrm e
-% .\tenrm l
-% .\tenrm l
-% .\tenrm o
-% .\glue 3.33333 plus 1.66666 minus 1.11111
-% .\tenit w
-% .\tenit o
-% .\tenit r
-% .\tenit l
-% .\tenit d
-%
-% .\glue 3.57774 plus 1.53333 minus 1.0222
-% .\mathon
-% .\teni a
-% .\glue(\thickmuskip) 2.77771 plus 2.77771
-% .\tenrm =
-% .\glue(\thickmuskip) 2.77771 plus 2.77771
-% .\teni b
-% .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217
-% .\tenrm +
-% .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217
-% .\teni c
-% .\mathoff
-%
-% ! OK.
-% l.9 \showbox0
-%
-%
-%   \end{BVerbatim}
-%   \qquad
-%   \begin{BVerbatim}[fontsize=\small]
-% > \box71=
-% \hbox(6.94444+0.83333)x91.35481
-% .\OT1/cmr/m/n/10 h
-% .\OT1/cmr/m/n/10 e
-% .\OT1/cmr/m/n/10 l
-% .\OT1/cmr/m/n/10 l
-% .\OT1/cmr/m/n/10 o
-% .\glue 3.33333 plus 1.66666 minus 1.11111
-% .\OT1/cmr/m/it/10 w
-% .\OT1/cmr/m/it/10 o
-% .\OT1/cmr/m/it/10 r
-% .\OT1/cmr/m/it/10 l
-% .\OT1/cmr/m/it/10 d
-% .\kern 1.03334
-% .\glue 3.33333 plus 1.66666 minus 1.11111
-% .\mathon
-% .\OML/cmm/m/it/10 a
-% .\glue(\thickmuskip) 2.77771 plus 2.77771
-% .\OT1/cmr/m/n/10 =
-% .\glue(\thickmuskip) 2.77771 plus 2.77771
-% .\OML/cmm/m/it/10 b
-% .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217
-% .\OT1/cmr/m/n/10 +
-% .\glue(\medmuskip) 2.22217 plus 1.11108 minus 2.22217
-% .\OML/cmm/m/it/10 c
-% .\mathoff
-%
-% ! OK.
-% <argument> \l_tmp_box
-%
-% l.12 \box_show:N \l_tmp_box
-%   \end{BVerbatim}
-%   \caption{Output from displaying the contents of a simple box to the log file, using plain \TeX{} (left) and \pkg{expl3} (right). Some blank lines have been added to the plain \TeX{} version to help with the comparison.}
-%   \label{fig:box-log}
-% \end{figure}
-%
-% \subsection{Additional test tasks}
-%
-% A standard test will run the file \texttt{\meta{name}.lvt} using one
-% or more engines, but will not carry out any additional processing. For
-% some tests, for example bibliography generation, it may be desirable to
-% call one or more tools in addition to the engine. This can be arranged
-% by defining |runtest_tasks|, a function taking one argument, the name
-% of the current test (this is equivalent to \TeX{}'s \cs{jobname},
-% \emph{i.e.}~it lacks an extension). The function |runtest_tasks|
-% is is into a call to the system to run the engine. As such, it
-% should take return a string with the appropriate command(s)
-% and option(s). If more than one task is required, these should be separated
-% by use of |os_concat|, a string variable defined by \pkg{l3build} as the
-% correct concatenation marker for the system. An example of |runtest_tasks|
-% suitable for calling Biber is shown in Listing~\ref{fig:test-tasks}.
-% \begin{figure}
-%   \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6]
-%     function runtest_tasks(name)
-%       return "biber " .. name
-%     end
-%   \end{lstlisting}
-%   \caption{Example \texttt{runtest_tasks} function.}
-%   \label{fig:test-tasks}
-% \end{figure}
-%
-% \section{Alternative test formats}
-%
-% \subsection{Generating test files with \pkg{DocStrip}}
-%
-% It is  possible to pack tests inside source files. Tests generated during the
-% unpacking process will be available to the \texttt{check} and \texttt{save}
-% commands as if they were stored in the \texttt{testfiledir}. Any explicit
-% test files inside \texttt{testfiledir} take priority over generated ones
-% with the same names.
-%
-% \subsection{Specifying expectations}
-%
-% Regression tests check whether changes introduced in the code modify the test
-% output. Especially while developing a complex package there is not yet a
-% baseline to save a test goal with. It might then be easier to formulate the
-% expected effects and outputs of tests directly. To achieve this, you may
-% create an \texttt{.lve} instead of a \texttt{.tlg}
-% file.\footnote{Mnemonic: \texttt{lv\textbf{t}}: \textbf{t}est,
-% \texttt{lv\textbf{e}}: \textbf{e}xpectation} It is processed exactly like
-% the \texttt{.lvt} to generate the expected outcome. The test fails when both
-% differ.
-%
-% Combining both features enables contrasting the test with its expected
-% outcome in a compact format. Listing \ref{fig:expect-dtx} exemplary tests
-% \TeX{}s counters. Listing \ref{fig:expect-ins} shows the relevant part of an
-% \texttt{.ins} file to generate it.
-%
-% \begin{figure}
-%   \begin{lstlisting}[frame=single,language={TeX},gobble = 6]
-%     \input regression-test.tex\relax
-%     \START
-%     \TEST{counter-math}{
-%     %<*test>
-%       \OMIT
-%       \newcounter{numbers}
-%       \setcounter{numbers}{2}
-%       \addtocounter{numbers}{2}
-%       \stepcounter{numbers}
-%       \TIMO
-%       \typeout{\arabic{numbers}}
-%     %</test>
-%     %<expect>  \typeout{5}
-%     }
-%     \END
-%   \end{lstlisting}
-%   \caption{Test and expectation can be specified side-by-side in a single
-%     \texttt{.dtx} file.}
-%   \label{fig:expect-dtx}
-% \end{figure}
-%
-%\begin{figure}
-%   \begin{lstlisting}[frame=single,language={TeX},gobble = 6]
-%      \generate{\file{\jobname.lvt}{\from{\jobname.dtx}{test}}
-%                \file{\jobname.lve}{\from{\jobname.dtx}{expect}}}
-%   \end{lstlisting}
-%   \caption{Test and expectation are generated from a \texttt{.dtx} file of
-%     the same name.}
-%   \label{fig:expect-ins}
-% \end{figure}
-%
-% \section{Release-focussed features}
-%
-% \subsection{Automatic version modification}
-%
-% As detailed above, the |setversion| target will automatically edit
-% source files to modify date and version. This behaviour is governed by
-% variable \var{versionform}. As standard, no automatic replacement
-% takes place, but setting \var{versionform} will allow this to happen,
-% with options
-% \begin{itemize}
-%   \item |ProvidesPackage| --- Searches for lines using the \LaTeXe{}
-%     \cs{ProvidesPackage}, \cs{ProvidesClass} and \cs{ProvidesFile}
-%     identifiers (as a whole line).
-%   \item |ProvidesExplPackage| --- Searches for lines using the \pkg{expl3}
-%     \cs{ProvidesExplPackage}, \cs{ProvidesExplClass} and
-%     \cs{ProvidesExplFile} identifiers (at the start of a line).
-%   \item |filename| --- Searches for lines using |\def\filename|,
-%     |\def\filedate|, \dots, formulation.
-%   \item |ExplFileDate| --- Searches for lines using |\def\ExplFileDate|,
-%     \dots, formulation.
-% \end{itemize}
-%
-% For more complex cases, the programmer may directly define the
-% Lua function |setversion_update_line()|, which takes as arguments the line of the
-% source, the supplied date and the supplied version. It should return a
-% (possibly unmodified) line and may use one, both or neither of the
-% date and version to update the line. Typically, |setversion_update_line| should
-% match to the exact pattern used by the programmer in the source files.
-% For example, for code using macros for the date and version
-% a suitable function might read as shown in Figure~\ref{fig:update-line}.
-% \begin{figure}
-%   \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6]
-%     function setversion_update_line(line, date, release)
-%       -- No real regex so do it one type at a time
-%       for _,i in pairs({"Class", "File", "Package"}) do
-%         if string.match(
-%           line,
-%           "^\\Provides" .. i .. "{[a-zA-Z0-9%-]+}%[[^%]]*%]$"
-%         ) then
-%           line = string.gsub(line, "%[%d%d%d%d/%d%d/%d%d", "["
-%             .. string.gsub(date, "%-", "/")
-%           line = string.gsub(
-%             line, "(%[%d%d%d%d/%d%d/%d%d) [^ ]*", "%1 " .. release
-%           )
-%           break
-%         end
-%       end
-%       return line
-%     end
-%   \end{lstlisting}
-%   \caption{Example \texttt{setversion_update_line} function.}
-%   \label{fig:update-line}
-% \end{figure}
-%
-% \subsection{Typesetting documentation}
-%
-% As part of the overall build process, \pkg{l3build} will create PDF
-% documentation as described earlier. The standard build process for PDFs
-% will attempt to run Biber, \BibTeX{} and MakeIndex as appropriate
-% (the exact binaries used are defined by \luavar{biberexe}, \luavar{bibtexexe}
-% and \luavar{makeindexexe}). However, there is no attempt to create an entire
-% PDF creation system in the style of \texttt{latexmk} or similar.
-%
-% For package authors who have more complex requirements than those covered
-% by the standard set up, the Lua script offers the possibility for
-% customisation. The Lua function \texttt{typeset} may be defined before
-% reading \texttt{l3build.lua} and should take one argument, the name of
-% the file to be typeset. Within this function, the auxiliary Lua
-% functions \texttt{biber}, \texttt{bibtex}, \texttt{makeindex} and
-% \texttt{tex} can be used, along with custom code, to define a PDF
-% typesetting pathway. The functions \texttt{biber} and \texttt{bibtex}
-% take a single argument: the name of the file to work with \emph{minus}
-% any extension. The \texttt{tex} takes as an argument the full name
-% of the file. The most complex function \texttt{makeindex} requires the
-% name, input extension, output extension, log extension and style name.
-% For example,  Figure~\ref{fig:PDF} shows a simple script which might
-% apply to a case where multiple \BibTeX{} runs are needed (perhaps where
-% citations can appear within other references).
-%
-% \begin{figure}[!b]
-%   \begin{lstlisting}[frame=single,language={[5.2]Lua},gobble = 6]
-%     #!/usr/bin/env texlua
-%
-%     -- Build script with custom PDF route
-%
-%     module = "mymodule"
-%
-%     function typeset(file)
-%       local name = jobname(file)
-%       local errorlevel = tex (file)
-%       if errorlevel == 0 then
-%         -- Return a non-zero errorlevel if anything goes wrong
-%         errorlevel =(
-%           bibtex(name) +
-%           tex(file)    +
-%           bibtex(name) +
-%           tex(file)    +
-%           tex(file)
-%         )
-%       end
-%       return errorlevel
-%     end
-%
-%     kpse.set_program_name("kpsewhich")
-%     dofile(kpse.lookup("l3build.lua"))
-%   \end{lstlisting}
-%   \caption{A customised PDF creation script.}
-%   \label{fig:PDF}
-% \end{figure}
-%
-% \section{Lua interfaces}
-%
-% Whilst for the majority of users the simple variable-based control methods
-% outlined above will suffice, for more advanced applications there will be
-% a need to adjust behavior by using interfaces within the Lua code. This
-% section details the global variables and functions provided.
-%
-% \subsection{Global variables}
-%
-% \begin{variable}{options}
-%   The |options| table holds the values passed to \pkg{l3build} at the
-%   command line. The possible entries in the table are given in the table
-%   below.
-%   \begin{center}
-%   \begin{tabular}{ll}
-%     \toprule
-%     Entry & Type \\
-%     \midrule
-%       \var{date}        & String  \\
-%       \var{engine}      & Table   \\
-%       \var{files}       & Table   \\
-%       \var{halt}        & Boolean \\
-%       \var{help}        & Boolean \\
-%       \var{pdf}         & Boolean \\
-%       \var{quiet}       & Boolean \\
-%       \var{release}     & String  \\
-%       \var{testfiledir} & String  \\
-%     \bottomrule
-%     \end{tabular}
-%   \end{center}
-% \end{variable}
-%
-% \subsection{Utility functions}
-%
-% The utility functions are largely focussed on file operations, though a small
-% number of others are provided. File paths should be given in Unix style
-% (using |/| as a path separator). File operations take place relative to the
-% path from which \pkg{l3build} is called. File operation syntax is largely
-% modelled on Unix command line commands but reflect the need to work on
-% Windows in a flexible way.
-%
-% \begin{function}{abspath()}
-%   \begin{syntax}
-%     |abspath(|\meta{target}|)|
-%   \end{syntax}
-%   Returns a string which gives the absolute location of the
-%   \meta{target} directory.
-% \end{function}
-%
-% \begin{function}{dirname()}
-%   \begin{syntax}
-%     |dirname(|\meta{file}|)|
-%   \end{syntax}
-%   Returns a string comprising the path to a \meta{file} with the name removed
-%   (\emph{i.e.}~up to the last |/|). Where the \meta{file} has no path data,
-%   |"."| is returned.
-% \end{function}
-%
-% \begin{function}{basename()}
-%   \begin{syntax}
-%     |basename(|\meta{file}|)|
-%   \end{syntax}
-%   Returns a string comprising the full name of the \meta{file} with the
-%   path removed (\emph{i.e.}~from the last |/| onward).
-% \end{function}
-%
-% \begin{function}{cleandir()}
-%   \begin{syntax}
-%     |cleandir(|\meta{dir}|)|
-%   \end{syntax}
-%   Removes any content within the \meta{dir}; returns an error level.
-% \end{function}
-%
-% \begin{function}{cp()}
-%   \begin{syntax}
-%     |cp(|\meta{glob}, \meta{source}, \meta{destination}|)|
-%   \end{syntax}
-%   Copies files matching the \meta{glob} from the \meta{source} directory
-%   to the \meta{destination}; returns an error level.
-% \end{function}
-%
-% \begin{function}{direxists()}
-%   \begin{syntax}
-%     |direxists(|\meta{dir}|)|
-%   \end{syntax}
-%   Tests if the \meta{dir} exists; returns a boolean value.
-% \end{function}
-%
-% \begin{function}{fileexists()}
-%   \begin{syntax}
-%     |fileexists(|\meta{file}|)|
-%   \end{syntax}
-%   Tests if the \meta{file} exists; returns a boolean value.
-% \end{function}
-%
-% \begin{function}{filelist()}
-%   \begin{syntax}
-%     |filelist(|\meta{path}, \oarg{glob}|)|
-%   \end{syntax}
-%   Returns a table containing all of the files with the \meta{path}
-%   which match the \meta{glob}; if the latter is absent returns a list of
-%   all files in the \meta{path}.
-% \end{function}
-%
-% \begin{function}{jobname()}
-%   \begin{syntax}
-%     |jobname(|\meta{file}|)|
-%   \end{syntax}
-%   Returns a string comprising the jobname of the file with the
-%   path and extension removed (\emph{i.e.}~from the last |/| up to the
-%   last |.|).
-% \end{function}
-%
-% \begin{function}{mkdir()}
-%   \begin{syntax}
-%     |mkdir(|\meta{dir}|)|
-%   \end{syntax}
-%   Creates the \meta{dir}; returns an error level.
-% \end{function}
-%
-% \begin{function}{ren()}
-%   \begin{syntax}
-%     |ren(|\meta{dir}, \meta{source}, \meta{destination}|)|
-%   \end{syntax}
-%   Renames the \meta{source} file to the \meta{destination} name within
-%   the \meta{dir}; returns an error level.
-% \end{function}
-%
-% \begin{function}{rm()}
-%   \begin{syntax}
-%     |rm(|\meta{dir}, \meta{glob}|)|
-%   \end{syntax}
-%   Removes files in the \meta{dir} matching the \meta{glob}; returns an
-%   error level.
-% \end{function}
-%
-% \begin{function}{run()}
-%   \begin{syntax}
-%     |run(|\meta{dir}, \meta{cmd}|)|
-%   \end{syntax}
-%   Executes the \meta{cmd}, starting it in the \meta{dir}; returns an
-%   error level.
-% \end{function}
-%
-% \begin{function}{spltpath()}
-%   \begin{syntax}
-%     |splitpath(|\meta{file}|)|
-%   \end{syntax}
-%   Returns two strings split at the last |/|: the \texttt{dirname()} and
-%   the |basename()|.
-% \end{function}
-%
-% \begin{function}{unix_to_win()}
-%   \begin{syntax}
-%     |unix_to_win(|\meta{path}|)|
-%   \end{syntax}
-%   Returns a string comprising the \meta{path} with |/| characters replaced
-%   by |\\|  and thus suitable for use with Windows-specific commands which
-%   require this form of path.
-% \end{function}
-%
-% \subsection{System-dependent strings}
-%
-% To support creation of additional functionality, the following low-level
-% strings are exposed by \pkg{l3build}: these all have system-dependent
-% definitions and avoid the need to test |os.type| during the construction
-% of system calls.
-%
-% \begin{variable}{os_concat}
-%   The concatenation operation for using multiple commands in one
-%   system call, \emph{e.g.}
-%   \begin{verbatim}
-%     os.execute("tex " .. file .. os_concat .. "tex " .. file)
-%   \end{verbatim}
-% \end{variable}
-%
-% \begin{variable}{os_null}
-%   The location to redirect commands which should produce no output
-%   at the terminal: almost always used preded by |>|, \emph{e.g.}
-%   \begin{verbatim}
-%     os.execute("tex " .. file .. " > " .. os_null)
-%   \end{verbatim}
-% \end{variable}
-%
-% \begin{variable}{os_pathsep}
-%   The separator used when setting an environment variable to multiple
-%   paths, \emph{e.g.}
-%   \begin{verbatim}
-%     os.execute(os_setenv .. " PATH=../a" .. os_pathsep .. "../b")
-%   \end{verbatim}
-% \end{variable}
-%
-% \begin{variable}{os_setenv}
-%   The command to set an environmental variable, \emph{e.g.}
-%   \begin{verbatim}
-%     os.execute(os_setenv .. " PATH=../a")
-%   \end{verbatim}
-% \end{variable}
-%
-% \begin{variable}{os_yes}
-%   A command to generate a series of $200$ lines each containing the
-%   character |y|: this is useful as the Unix |yes| command cannot be
-%   used inside |os.execute| (it does not terminate).
-% \end{variable}
-%
-% \end{documentation}
-%
-% \begin{implementation}
-%
-% \clearpage
-% \section{\texttt{regression-test.tex}}
-%
-% This section describes the code for setting up the regression test system.
-% Each test file should start with |\input regression-test.tex\relax|.
-%
-%    \begin{macrocode}
-%<*package>
-%    \end{macrocode}
-%
-% \subsection{Preliminaries}
-%
-% We require \eTeX{}.
-%    \begin{macrocode}
-\begingroup\expandafter\expandafter\expandafter\endgroup
-\expandafter\ifx\csname eTeXversion\endcsname\relax
-  \errmessage{e-TeX is required to use regression-test.tex}%
-  \expandafter\endinput
-\fi
-%    \end{macrocode}
-%
-% \begin{macro}{\reset at catcodes}
-%   Unlike in the \LaTeXe{} regression test suite, reset catcodes: each test
-%   should set these as appropriate. There's also a quick test for Con\TeX{}t:
-%   it defines |\unprotect| which should be a reasonable marker (and is
-%   needed as some catcodes are otherwise wrong).
-%    \begin{macrocode}
-\ifx\unprotect\undefined
-  \expandafter\edef\csname reset\string @catcodes\endcsname{%
-    \catcode`\noexpand\@=\the\catcode`\@\relax
-  }%
-  \catcode`\@=11 %
-\else
-  \unprotect
-  \def\reset at catcodes{\protect}%
-\fi
-%    \end{macrocode}
-% \end{macro}
-%
-% Put \TeX{} into scroll mode, and stop it showing the
-% implementation details of macros in error messages.
-%    \begin{macrocode}
-\ifnum\interactionmode>1 \scrollmode\fi
-\errorcontextlines=-1 %
-%    \end{macrocode}
-%
-% Show all box details: this avoids getting variable results if boxes
-% have different numbers of lines (\LuaTeX{} adds extra information).
-%    \begin{macrocode}
-\showboxbreadth=\maxdimen
-\showboxdepth=\maxdimen
-%    \end{macrocode}
-%
-% \begin{macro}{\logginoutput}
-%   The |\showoutput| command of \LaTeX{} calls |\loggingoutput| which in turn
-%   calls |\errorstopmode| but we want to continue running without any stops.
-%    \begin{macrocode}
-\def\loggingoutput{%
-  \tracingoutput=1 %
-  \showboxbreadth=\maxdimen
-  \showboxdepth=\maxdimen
-}
-%    \end{macrocode}
-% \end{macro}
-%
-% Set the newline character: \LaTeXe{} does this but plain-based formats do
-% not.
-%    \begin{macrocode}
-\newlinechar=`\^^J
-%    \end{macrocode}
-%
-% \subsection{Commands in test files}
-%
-% \begin{macro}{\LONGTYPEOUT, \TYPE}
-%   A long version of |\typeout|, because tests may contain |\par| tokens.
-%   Besides, with that |\TYPE|, we can do
-%   |\TYPE { ... \TRUE ... \NEWLINE ... }|.
-%    \begin{macrocode}
-\long\def\LONGTYPEOUT#1{%
-  \begingroup
-    \long\def\TYPE##1{##1}%
-    \immediate\write128{#1}%
-  \endgroup
-}
-\let\TYPE\LONGTYPEOUT
-%    \end{macrocode}
-%
-% \begin{macro}{\STARTMESSAGE, \START}
-%   Start the test, after the optional |\documentclass|
-%   |\begin{document}| commands with |\START|.  All lines in the |.log| file
-%   before this will be ignored.
-%    \begin{macrocode}
-\def\STARTMESSAGE{This is a generated file for the l3build validation system.}
-\def\START{%
-  \LONGTYPEOUT{^^JSTART-TEST-LOG^^J}%
-  \LONGTYPEOUT{^^J%
-     \STARTMESSAGE%
-     ^^J^^JDon't change this file in any respect.%
-     ^^J^^J%
-  }%
-}
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\@@@end, \END}
-% The test should end with |\END| or |\end{document}|
-% or |\bye| in plain \TeX{}.
-%    \begin{macrocode}
-\ifx\@@end\@undefined
-  \let\@@@end\end
-\else
-  \let\@@@end\@@end
-\fi
-\def\END{%
-  \ifnum\currentgrouplevel>0 %
-    \LONGTYPEOUT{Bad grouping: \the\currentgrouplevel!}%
-  \fi
-  \ifnum\currentiflevel>2 %
-    \LONGTYPEOUT{Bad conditionals: \the\numexpr\currentiflevel-2!}%
-  \fi
-  \LONGTYPEOUT{^^JEND-TEST-LOG^^J}%
-  \@@@end
-}
-\ifx\@@end\@undefined
-  \let\end\END
-\else
-  \let\@@end\END
-\fi
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\OMIT, \TIMO}
-%   Surround commands which produce irrelevant lines in the |.log| file by
-%   |\OMIT|\dots|\TIMO|
-%    \begin{macrocode}
-\def\OMIT{\LONGTYPEOUT{OMIT}}
-\def\TIMO{\LONGTYPEOUT{TIMO}}
-%    \end{macrocode}
-% \end{macro}
-%
-% To allow testing of possible changes, we allow extra code to be read
-% in before the test starts. The necessary code should be placed in a
-% file |regression-test.cfg|.
-%    \begin{macrocode}
-\ifx\InputIfFileExists\@undefined
-  \newread\@inputcheck
-  \long\def\InputIfFileExists#1#2#3{%
-    \openin\@inputcheck#1\relax
-    \ifeof\@inputcheck
-      \def\reserved at a{#3}%
-    \else
-      \def\reserved at a{#2\input #1\relax}%
-    \fi
-    \closein\@inputcheck
-    \reserved at a
-  }%
-\fi
-\InputIfFileExists{regression-test.cfg}
-  {\LONGTYPEOUT{^^J***^^Jregression-test.cfg in operation^^J***^^J}}{}
-%    \end{macrocode}
-%
-% \subsection{Formatting the \texttt{.log} file}
-%
-% \begin{macro}{\gTESTint}
-%   For tracking the total number of tests.
-%    \begin{macrocode}
-\newcount\gTESTint
-%     \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}
-%   {\SEPARATOR, \TEST, \TESTEXP, \TRUE, \FALSE, \YES, \NO, \NEWLINE}
-%   We are not starved for space in the log file output, so let's make it as
-%   verbose as is useful when reading the |.diff|'s.
-%    \begin{macrocode}
-\def\SEPARATOR{%
-  \TYPE{%
-    ============================================================%
-  }%
-}
-\long\def\TEST#1#2{%
-  \global\advance\gTESTint by 1 %
-  \SEPARATOR
-  \LONGTYPEOUT{TEST \the\gTESTint: \detokenize{#1}}%
-  \SEPARATOR
-  \begingroup
-    \let\TYPE\LONGTYPEOUT
-    #2%
-  \endgroup
-  \SEPARATOR
-  \LONGTYPEOUT{}%
-}
-\long\def\TESTEXP#1#2{%
-  \global\advance\gTESTint by 1 %
-  \SEPARATOR
-  \LONGTYPEOUT{%
-    TEST \the\gTESTint: \detokenize{#1}}%
-  \SEPARATOR
-  \begingroup
-    \long\def\TYPE##1{##1}%
-    \LONGTYPEOUT{#2}%
-  \endgroup
-  \SEPARATOR
-  \LONGTYPEOUT{}%
-}
-\def \TRUE  {\TYPE{TRUE}}
-\def \FALSE {\TYPE{FALSE}}
-\def \YES   {\TYPE{YES}}
-\def \NO    {\TYPE{NO}}
-\def \NEWLINE {\TYPE{^^J}}
-%    \end{macrocode}
-% \end{macro}
-%
-% \subsection{Suppressing variable data in output}
-%
-% Load the map file early so it does not appear in the log.
-%    \begin{macrocode}
-\ifx\pdfoutput\@undefined
-  \ifx\outputmode\@undefined
-  \else
-    \ifnum\outputmode>0 %
-      \pdfextension mapfile{pdftex.map}%
-    \fi
-  \fi
-\else
-  \ifnum\pdfoutput>0 %
-    \pdfmapfile{pdftex.map}%
-  \fi
-\fi
-%    \end{macrocode}
-%
-% To make any PDF file produced comparable we need to suppress various
-% pieces of data. This works in concert with setting the epoch from the
-% environment side (as not all output can be controlled here). We are
-% somewhat stuck if \texttt{dvips} is being used so just hope for the best!
-% There is a limit to what can be done with the underlying PDF structure so
-% there is no point entirely suppressing \texttt{Producer}: simply avoid
-% any version numbers.
-%    \begin{macrocode}
-\ifnum 0%
-  \ifx\pdfoutput\@undefined\else\ifnum\pdfoutput>0 1\fi\fi
-  \ifx\outputmode\@undefined\else\ifnum\outputmode>0 1\fi\fi
-  >0 %
-  \ifx\pdfvariable\@undefined
-    \pdfinfo{/Producer (\ifx\directlua\@undefined pdf\else Lua\fi TeX)}
-    \ifx\pdfinfoomitdate\@undefined\else
-      \pdfinfoomitdate     = 1 %
-      \pdfsuppressptexinfo = 1 %
-      \pdftrailerid{}
-    \fi
-  \else
-    \pdfextension info{/Producer (LuaTeX)}
-    \pdfvariable suppressoptionalinfo \numexpr
-          0
-        +   1 % PTEX.Fullbanner
-        +  32 % CreationDate
-        +  64 % ModDate
-      \relax
-  \fi
-\else
-  \special{%
-    pdf: docinfo
-      <<
-        /Creator        (TeX)
-        /CreationDate   ()
-        /ModDate        ()
-        /Producer       (\ifx\XeTeXversion\@undefined\else x\fi dvipdfmx)
-      >>
-  }
-\fi
-%    \end{macrocode}
-%
-% Finish up.
-%    \begin{macrocode}
-\reset at catcodes
-%    \end{macrocode}
-%
-%    \begin{macrocode}
-%</package>
-%    \end{macrocode}
-%
-% \newpage
-% \section{\texttt{l3build.lua}}
-%
-% This section consists of the |l3build.lua| code.
-% This code is \emph{not} generated from |l3build.dtx| since it needs to already be extracted to build \pkg{l3build} itself!
-% As Frank says, we don't want to end up with a double M\"unchhausen.
-%
-% \lstinputlisting
-%   [
-%    basicstyle=\ttfamily\scriptsize,
-%    numbers=left,
-%    numberstyle={\tiny\color[gray]{0.4}},
-%    language={[5.2]Lua},
-%    procnamekeys=function,
-%    procnamestyle=\color{red},
-%   ]
-%   {l3build.lua}
-%
-% \end{implementation}
-%
-% \PrintIndex
diff --git a/l3build/l3build.ins b/l3build/l3build.ins
deleted file mode 100644
index e943feb..0000000
--- a/l3build/l3build.ins
+++ /dev/null
@@ -1,56 +0,0 @@
-\iffalse meta-comment
-
-File l3build.ins Copyright (C) 2014,2016 The LaTeX3 Project
-
-It may be distributed and/or modified under the conditions of the
-LaTeX Project Public License (LPPL), either version 1.3c of this
-license or (at your option) any later version.  The latest version
-of this license is in the file
-
-   http://www.latex-project.org/lppl.txt
-
-This file is part of the "l3build bundle" (The Work in LPPL)
-and all files in that bundle must be distributed together.
-
------------------------------------------------------------------------
-
-The development version of the bundle can be found at
-
-   https://github.com/latex3/latex3
-
-for those people who are interested.
-
------------------------------------------------------------------------
-
-Any modification of this file should ensure that the copyright and
-license information is placed in the derived files.
-
-\fi
-
-\input docstrip.tex
-\askforoverwritefalse
-
-\preamble
-
-Copyright (C) 2014-2016 The LaTeX3 Project
-
-It may be distributed and/or modified under the conditions of
-the LaTeX Project Public License (LPPL), either version 1.3c of
-this license or (at your option) any later version.  The latest
-version of this license is in the file:
-
-   http://www.latex-project.org/lppl.txt
-
-This file is part of the "l3build bundle" (The Work in LPPL)
-and all files in that bundle must be distributed together.
-
-\endpreamble
-% stop docstrip adding \endinput
-\postamble
-\endpostamble
-
-\keepsilent
-
-\generate{\file{regression-test.tex}{\from{l3build.dtx}{package}}}
-
-\endbatchfile
diff --git a/l3build/l3build.lua b/l3build/l3build.lua
deleted file mode 100644
index be38a58..0000000
--- a/l3build/l3build.lua
+++ /dev/null
@@ -1,2317 +0,0 @@
---[[
-
-File l3build.lua Copyright (C) 2014-2017 The LaTeX3 Project
-
-It may be distributed and/or modified under the conditions of the
-LaTeX Project Public License (LPPL), either version 1.3c of this
-license or (at your option) any later version.  The latest version
-of this license is in the file
-
-   http://www.latex-project.org/lppl.txt
-
-This file is part of the "l3build bundle" (The Work in LPPL)
-and all files in that bundle must be distributed together.
-
------------------------------------------------------------------------
-
-The development version of the bundle can be found at
-
-   https://github.com/latex3/latex3
-
-for those people who are interested.
-
---]]
-
--- Version information
-release_date = "2017/05/29"
-
--- "module" is a deprecated function in Lua 5.2: as we want the name
--- for other purposes, and it should eventually be 'free', simply
--- remove the built-in
-if type(module) == "function" then
-  module = nil
-end
-
--- Ensure the module and bundle exist
-module = module or ""
-bundle = bundle or ""
-
--- Sanity check
-if module == "" and bundle == "" then
-  if string.match(arg[0], "l3build%.lua$") then
-    print(
-      "\n"
-        .. "Error: Call l3build using a configuration file, not directly.\n"
-    )
-  else
-    print(
-      "\n"
-        .. "Error: Specify either bundle or module in configuration script.\n"
-    )
-  end
-  os.exit(1)
-end
-
--- Directory structure for the build system
--- Use Unix-style path separators
-maindir     = maindir or "."
-
--- Substructure for tests and support files
-testfiledir = testfiledir or "testfiles"
-testsuppdir = testsuppdir or testfiledir .. "/support"
-supportdir  = supportdir  or maindir .. "/support"
-
--- Structure within a development area
-distribdir  = distribdir or maindir .. "/build/distrib"
-localdir    = localdir   or maindir .. "/build/local"
-testdir     = testdir    or maindir .. "/build/test"
-typesetdir  = typesetdir or maindir .. "/build/doc"
-unpackdir   = unpackdir  or maindir .. "/build/unpacked"
-
--- Substructure for CTAN release material
-ctandir     = ctandir or distribdir .. "/ctan"
-tdsdir      = tdsdir  or distribdir .. "/tds"
-tdsroot     = tdsroot or "latex"
-
--- Location for installation on CTAN or in TEXMFHOME
-if bundle == "" then
-  moduledir = tdsroot .. "/" .. module
-  ctanpkg   = ctanpkg or module
-else
-  moduledir = tdsroot .. "/" .. bundle .. "/" .. module
-  ctanpkg   = ctanpkg or bundle
-end
-
--- File types for various operations
--- Use Unix-style globs
--- All of these may be set earlier, so a initialised conditionally
-bibfiles           = bibfiles           or {"*.bib"}
-binaryfiles        = binaryfiles        or {"*.pdf", "*.zip"}
-bstfiles           = bstfiles           or {"*.bst"}
-checkfiles         = checkfiles         or { }
-checksuppfiles     = checksuppfiles     or { }
-cmdchkfiles        = cmdchkfiles        or { }
-cleanfiles         = cleanfiles         or {"*.log", "*.pdf", "*.zip"}
-demofiles          = demofiles          or { }
-docfiles           = docfiles           or { }
-excludefiles       = excludefiles       or {"*~"}
-installfiles       = installfiles       or {"*.sty"}
-makeindexfiles     = makeindexfiles     or {"*.ist"}
-sourcefiles        = sourcefiles        or {"*.dtx", "*.ins"}
-textfiles          = textfiles          or {"*.md", "*.txt"}
-typesetdemofiles   = typesetdemofiles   or { }
-typesetfiles       = typesetfiles       or {"*.dtx"}
-typesetsuppfiles   = typesetsuppfiles   or { }
-typesetsourcefiles = typesetsourcefiles or { }
-unpackfiles        = unpackfiles        or {"*.ins"}
-unpacksuppfiles    = unpacksuppfiles    or { }
-versionfiles       = versionfiles       or {"*.dtx"}
-
--- Roots which should be unpacked to support unpacking/testing/typesetting
-checkdeps   = checkdeps   or { }
-typesetdeps = typesetdeps or { }
-unpackdeps  = unpackdeps  or { }
-
--- Executable names plus following options
-typesetexe = typesetexe or "pdflatex"
-unpackexe  = unpackexe  or "tex"
-zipexe     = zipexe     or "zip"
-
-checkopts   = checkopts   or "-interaction=nonstopmode"
-cmdchkopts  = cmdchkopts  or "-interaction=batchmode"
-typesetopts = typesetopts or "-interaction=nonstopmode"
-unpackopts  = unpackopts  or ""
-zipopts     = zipopts     or "-v -r -X"
-
--- Engines for testing
-checkengines = checkengines or {"pdftex", "xetex", "luatex"}
-checkformat  = checkformat  or "latex"
-stdengine    = stdengine    or "pdftex"
-
--- Enable access to trees outside of the repo
--- As these may be set false, a more elaborate test than normal is needed
-if checksearch == nil then
-  checksearch = true
-end
-if typesetsearch == nil then
-  typesetsearch = true
-end
-if unpacksearch == nil then
-  unpacksearch = true
-end
-
--- Additional settings to fine-tune typesetting
-glossarystyle = glossarystyle or "gglo.ist"
-indexstyle    = indexstyle    or "gind.ist"
-
--- Supporting binaries and options
-biberexe      = biberexe      or "biber"
-biberopts     = biberopts     or ""
-bibtexexe     = bibtexexe     or "bibtex8"
-bibtexopts    = bibtexopts    or "-W"
-makeindexexe  = makeindexexe  or "makeindex"
-makeindexopts = makeindexopts or ""
-
--- Other required settings
-asciiengines = asciiengines or {"pdftex"}
-checkruns    = checkruns    or 1
-epoch        = epoch        or 1463734800
-maxprintline = maxprintline or 79
-packtdszip   = packtdszip   or false
-scriptname   = scriptname   or "build.lua"
-typesetcmds  = typesetcmds  or ""
-versionform  = versionform  or ""
-
--- Extensions for various file types: used to abstract out stuff a bit
-bakext = bakext or ".bak"
-dviext = dviext or ".dvi"
-logext = logext or ".log"
-lveext = lveext or ".lve"
-lvtext = lvtext or ".lvt"
-pdfext = pdfext or ".pdf"
-psext  = psext  or ".ps"
-tlgext = tlgext or ".tlg"
-
--- File operations are aided by the LuaFileSystem module
-local lfs = require("lfs")
-
--- Local access to functions
-local assert           = assert
-local ipairs           = ipairs
-local next             = next
-local print            = print
-local select           = select
-local tonumber         = tonumber
-local close            = io.close
-local lines            = io.lines
-local open             = io.open
-local output           = io.output
-local stderr           = io.stderr
-local write            = io.write
-local set_program_name = kpse.set_program_name
-local var_value        = kpse.var_value
-local lfs_attributes   = lfs.attributes
-local lfs_dir          = lfs.dir
-local os_date          = os.date
-local execute          = os.execute
-local exit             = os.exit
-local getenv           = os.getenv
-local os_remove        = os.remove
-local os_type          = os.type
-local luatex_revision  = status.luatex_revision
-local luatex_version   = status.luatex_version
-local char             = string.char
-local find             = string.find
-local format           = string.format
-local gmatch           = string.gmatch
-local gsub             = string.gsub
-local len              = string.len
-local match            = string.match
-local sub              = string.sub
-local concat           = table.concat
-local insert           = table.insert
-local utf8_char        = unicode.utf8.char
-
--- Parse command line options
--- This is done as a function (rather than do ... end) as it allows early
--- termination (break)
-local function argparse()
-  local result = { }
-  local files  = { }
-  local long_options =
-    {
-      date                = "date"       ,
-      engine              = "engine"     ,
-      ["halt-on-error"]   = "halt"       ,
-      ["halt-on-failure"] = "halt"       ,
-      help                = "help"       ,
-      pdf                 = "pdf"        ,
-      quiet               = "quiet"      ,
-      release             = "release"    ,
-      testfiledir         = "testfiledir"
-    }
-  local short_options =
-    {
-      d = "date"       ,
-      e = "engine"     ,
-      h = "help"       ,
-      H = "halt"       ,
-      p = "pdf"        ,
-      q = "quiet"      ,
-      r = "release"    ,
-      t = "testfiledir"
-    }
-  local option_args =
-    {
-      date        = true ,
-      engine      = true ,
-      halt        = false,
-      help        = false,
-      pdf         = false,
-      quiet       = false,
-      release     = true,
-      testfiledir = true
-    }
-  local args = args
-  -- arg[1] is a special case: must be a command or "-h"/"--help"
-  -- Deal with this by assuming help and storing only apparently-valid
-  -- input
-  local a = arg[1]
-  result["target"] = "help"
-  if a then
-    -- No options are allowed in position 1, so filter those out
-    if not match(a, "^%-") then
-      result["target"] = a
-    end
-  end
-  -- Stop here if help is required
-  if result["target"] == "help" then
-    return result
-  end
-  -- An auxiliary to grab all file names into a table
-  local function remainder(num)
-    local files = { }
-    for i = num, #arg do
-      insert(files, arg[i])
-    end
-    return files
-  end
-  -- Examine all other arguments
-  -- Use a while loop rather than for as this makes it easier
-  -- to grab arg for optionals where appropriate
-  local i = 2
-  while i <= #arg do
-    local a = arg[i]
-    -- Terminate search for options
-    if a == "--" then
-      files = remainder(i + 1)
-      break
-    end
-    -- Look for optionals
-    local opt
-    local optarg
-    local opts
-    -- Look for and option and get it into a variable
-    if match(a, "^%-") then
-      if match(a, "^%-%-") then
-        opts = long_options
-        local pos = find(a, "=", 1, true)
-        if pos then
-          opt    = sub(a, 3, pos - 1)
-          optarg = sub(a, pos + 1)
-        else
-          opt = sub(a, 3)
-        end
-      else
-        opts = short_options
-        opt  = sub(a, 2, 2)
-        -- Only set optarg if it is there
-        if #a > 2 then
-          optarg = sub(a, 3)
-        end
-      end
-      -- Now check that the option is valid and sort out the argument
-      -- if required
-      local optname = opts[opt]
-      if optname then
-        local reqarg = option_args[optname]
-        -- Tidy up arguments
-        if reqarg and not optarg then
-          optarg = arg[i + 1]
-          if not optarg then
-            stderr:write("Missing value for option " .. a .."\n")
-            return {"help"}
-          end
-          i = i + 1
-        end
-        if not reqarg and optarg then
-          stderr:write("Value not allowed for option " .. a .."\n")
-          return {"help"}
-        end
-      else
-        stderr:write("Unknown option " .. a .."\n")
-        return {"help"}
-      end
-      -- Store the result
-      if optarg then
-        local opts = result[optname] or { }
-        for hit in gmatch(optarg, "([^,%s]+)") do
-          insert(opts, hit)
-        end
-        result[optname] = opts
-      else
-        result[optname] = true
-      end
-      i = i + 1
-    end
-    if not opt then
-      files = remainder(i)
-      break
-    end
-  end
-  result["files"] = files
-  return result
-end
-
-options = argparse()
-
-local optdate    = options["date"]
-local optengines = options["engine"]
-local opthalt    = options["halt"]
-local optpdf     = options["pdf"]
-local optquiet   = options["quiet"]
-local optrelease = options["release"]
-
--- Convert a file glob into a pattern for use by e.g. string.gub
--- Based on https://github.com/davidm/lua-glob-pattern
--- Simplified substantially: "[...]" syntax not supported as is not
--- required by the file patterns used by the team. Also note style
--- changes to match coding approach in rest of this file.
---
--- License for original globtopattern
---[[
-
-   (c) 2008-2011 David Manura.  Licensed under the same terms as Lua (MIT).
-
-  Permission is hereby granted, free of charge, to any person obtaining a copy
-  of this software and associated documentation files (the "Software"), to deal
-  in the Software without restriction, including without limitation the rights
-  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-  copies of the Software, and to permit persons to whom the Software is
-  furnished to do so, subject to the following conditions:
-
-  The above copyright notice and this permission notice shall be included in
-  all copies or substantial portions of the Software.
-
-  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-  THE SOFTWARE.
-  (end license)
-
---]]
-local function glob_to_pattern(glob)
-
-  local pattern = "^" -- pattern being built
-  local i = 0 -- index in glob
-  local char -- char at index i in glob
-
-  -- escape pattern char
-  local function escape(char)
-    return match(char, "^%w$") and char or "%" .. char
-  end
-
-  -- Convert tokens.
-  while true do
-    i = i + 1
-    char = sub(glob, i, i)
-    if char == "" then
-      pattern = pattern .. "$"
-      break
-    elseif char == "?" then
-      pattern = pattern .. "."
-    elseif char == "*" then
-      pattern = pattern .. ".*"
-    elseif char == "[" then
-      -- Ignored
-      print("[...] syntax not supported in globs!")
-    elseif char == "\\" then
-      i = i + 1
-      char = sub(glob, i, i)
-      if char == "" then
-        pattern = pattern .. "\\$"
-        break
-      end
-      pattern = pattern .. escape(char)
-    else
-      pattern = pattern .. escape(char)
-    end
-  end
-  return pattern
-end
-
--- Detect the operating system in use
--- Support items are defined here for cases where a single string can cover
--- both Windows and Unix cases: more complex situations are handled inside
--- the support functions
-os_concat  = ";"
-os_null    = "/dev/null"
-os_pathsep = ":"
-os_setenv  = "export"
-os_yes     = "printf 'y\\n%.0s' {1..200}"
-local os_ascii   = "echo \"\""
-local os_cmpexe  = getenv("cmpexe") or "cmp"
-local os_cmpext  = getenv("cmpext") or ".cmp"
-local os_diffext = getenv("diffext") or ".diff"
-local os_diffexe = getenv("diffexe") or "diff -c --strip-trailing-cr"
-local os_grepexe = "grep"
-local os_newline = "\n"
-if os_type == "windows" then
-  os_ascii   = "@echo."
-  os_cmpexe  = getenv("cmpexe") or "fc /b"
-  os_cmpext  = getenv("cmpext") or ".cmp"
-  os_concat  = "&"
-  os_diffext = getenv("diffext") or ".fc"
-  os_diffexe = getenv("diffexe") or "fc /n"
-  os_grepexe = "findstr /r"
-  os_newline = "\n"
-  if tonumber(luatex_version) < 100 or
-     (tonumber(luatex_version) == 100
-       and tonumber(luatex_revision) < 4) then
-    os_newline = "\r\n"
-  end
-  os_null    = "nul"
-  os_pathsep = ";"
-  os_setenv  = "set"
-  os_yes     = "for /l %I in (1,1,200) do @echo y"
-end
-
--- Return an absolute path from a relative one
-function abspath(path)
-  local oldpwd = lfs.currentdir()
-  lfs.chdir(path)
-  local result = lfs.currentdir()
-  lfs.chdir(oldpwd)
-  return gsub(result, "\\", "/")
-end
-
--- For cleaning out a directory, which also ensures that it exists
-function cleandir(dir)
-  local errorlevel = mkdir(dir)
-  if errorlevel ~= 0 then
-    return errorlevel
-  end
-  return rm(dir, "*")
-end
-
--- Copy files 'quietly'
-function cp(glob, source, dest)
-  local errorlevel
-  for i,_ in pairs(tree(source, glob)) do
-    local source = source .. "/" .. i
-    if os_type == "windows" then
-      if lfs_attributes(source)["mode"] == "directory" then
-        errorlevel = execute(
-          "xcopy /y /e /i " .. unix_to_win(source) .. " "
-             .. unix_to_win(dest .. "/" .. i) .. " > nul"
-        )
-      else
-        errorlevel = execute(
-          "xcopy /y " .. unix_to_win(source) .. " "
-             .. unix_to_win(dest) .. " > nul"
-        )
-      end
-    else
-      errorlevel = execute("cp -rf " .. source .. " " .. dest)
-    end
-    if errorlevel ~=0 then
-      return errorlevel
-    end
-  end
-  return 0
-end
-
--- OS-dependent test for a directory
-function direxists(dir)
-  local errorlevel
-  if os_type == "windows" then
-    errorlevel =
-      execute("if not exist \"" .. unix_to_win(dir) .. "\" exit 1")
-  else
-    errorlevel = execute("[ -d " .. dir .. " ]")
-  end
-  if errorlevel ~= 0 then
-    return false
-  end
-  return true
-end
-
-function fileexists(file)
-  local f = open(file, "r")
-  if f ~= nil then
-    close(f)
-    return true
-  else
-    return false
-  end
-end
-
--- Generate a table containing all file names of the given glob or all files
--- if absent
-function filelist(path, glob)
-  local files = { }
-  local pattern
-  if glob then
-    pattern = glob_to_pattern(glob)
-  end
-  if direxists(path) then
-    for entry in lfs_dir(path) do
-      if pattern then
-        if match(entry, pattern) then
-          insert(files, entry)
-        end
-      else
-        if entry ~= "." and entry ~= ".." then
-          insert(files, entry)
-        end
-      end
-    end
-  end
-  return files
-end
-
--- Does what filelist does, but can also glob subdirectories. In the returned
--- table, the keys are paths relative to the given starting path, the values
--- are their counterparts relative to the current working directory.
-function tree(path, glob)
-  function cropdots(path)
-    return gsub(gsub(path, "^%./", ""), "/%./", "/")
-  end
-  function always_true()
-    return true
-  end
-  function is_dir(file)
-    return lfs.attributes(file)["mode"] == "directory"
-  end
-  local dirs = {["."]=cropdots(path)}
-  for pattern, critereon in gmatch(cropdots(glob), "([^/]+)(/?)") do
-    local critereon = critereon == "/" and is_dir or always_true
-    function fill(path, dir, table)
-      for _, file in ipairs(filelist(dir, pattern)) do
-        local fullpath = path .. "/" .. file
-        if file ~= "." and file ~= ".." and
-          fullpath ~= maindir .. "/build" and
-          (string.sub(pattern, 1, 1) == "."
-            or string.sub(file, 1, 1) ~= ".")
-        then
-          local fulldir = dir .. "/" .. file
-          if critereon(fulldir) then
-            table[fullpath] = fulldir
-          end
-        end
-      end
-    end
-    local newdirs = {}
-    if pattern == "**" then
-      while true do
-        path, dir = next(dirs)
-        if not path then
-          break
-        end
-        dirs[path] = nil
-        newdirs[path] = dir
-        fill(path, dir, dirs)
-      end
-    else
-      for path, dir in pairs(dirs) do
-        fill(path, dir, newdirs)
-      end
-    end
-    dirs = newdirs
-  end
-  return dirs
-end
-
-function mkdir(dir)
-  if os_type == "windows" then
-    -- Windows (with the extensions) will automatically make directory trees
-    -- but issues a warning if the dir already exists: avoid by including a test
-    local dir = unix_to_win(dir)
-    return execute(
-      "if not exist "  .. dir .. "\\nul " .. "mkdir " .. dir
-    )
-  else
-    return execute("mkdir -p " .. dir)
-  end
-end
-
--- Rename
-function ren(dir, source, dest)
-  local dir = dir .. "/"
-  if os_type == "windows" then
-    return execute("ren " .. unix_to_win(dir) .. source .. " " .. dest)
-  else
-    return execute("mv " .. dir .. source .. " " .. dir .. dest)
-  end
-end
-
--- Remove file(s) based on a glob
-function rm(source, glob)
-  for _,i in ipairs(filelist(source, glob)) do
-    os_remove(source .. "/" .. i)
-  end
-  -- os_remove doesn't give a sensible errorlevel
-  return 0
-end
-
--- Remove a directory tree
-function rmdir(dir)
-  -- First, make sure it exists to avoid any errors
-  mkdir(dir)
-  if os_type == "windows" then
-    return execute("rmdir /s /q " .. unix_to_win(dir))
-  else
-    return execute("rm -r " .. dir)
-  end
-end
-
--- Run a command in a given directory
-function run(dir, cmd)
-  return execute("cd " .. dir .. os_concat .. cmd)
-end
-
--- Deal with the fact that Windows and Unix use different path separators
-function unix_to_win(path)
-  return gsub(path, "/", "\\")
-end
-
---
--- Auxiliary functions which are used by more than one main function
---
-
--- Do some subtarget for all modules in a bundle
-local function allmodules(target)
-  local date = ""
-  if optdate then
-    date = " --date=" .. optdate[1]
-  end
-  local engines = ""
-  if optengines then
-    engines = " --engine=" .. concat(optengines, ",")
-  end
-  local release = ""
-  if optrelease then
-    release = " --release=" .. optrelease[1]
-  end
-  for _,i in ipairs(modules) do
-    print(
-      "Running script " .. scriptname .. " with target \"" .. target
-        .. "\" for module "
-        .. i
-    )
-    local errorlevel = run(
-      i,
-      "texlua " .. scriptname .. " " .. target
-        .. (opthalt and " -H" or "")
-        .. date
-        .. engines
-        .. (optpdf and " -p" or "")
-        .. (optquiet and " -q" or "")
-        .. release
-    )
-    if errorlevel ~= 0 then
-      return errorlevel
-    end
-  end
-  return 0
-end
-
--- Set up the check system files: needed for checking one or more tests and
--- for saving the test files
-function checkinit()
-  cleandir(testdir)
-  depinstall(checkdeps)
-  -- Copy dependencies to the test directory itself: this makes the paths
-  -- a lot easier to manage, and is important for dealing with the log and
-  -- with file input/output tests
-  for _,i in ipairs(filelist(localdir)) do
-    cp(i, localdir, testdir)
-  end
-  bundleunpack({".", testfiledir})
-  for _,i in ipairs(installfiles) do
-    cp(i, unpackdir, testdir)
-  end
-  for _,i in ipairs(checkfiles) do
-    cp(i, unpackdir, testdir)
-  end
-  if direxists(testsuppdir) then
-    for _,i in ipairs(filelist(testsuppdir)) do
-      cp(i, testsuppdir, testdir)
-    end
-  end
-  for _,i in ipairs(checksuppfiles) do
-    cp(i, supportdir, testdir)
-  end
-  execute(os_ascii .. ">" .. testdir .. "/ascii.tcx")
-end
-
--- Copy files to the main CTAN release directory
-function copyctan()
-  -- Do all of the copying in one go
-  for _,i in ipairs(
-      {
-        bibfiles,
-        demofiles,
-        docfiles,
-        pdffiles,
-        sourcefiles,
-        textfiles,
-        typesetlist
-      }
-    ) do
-    for _,j in ipairs(i) do
-      cp(j, ".", ctandir .. "/" .. ctanpkg)
-    end
-  end
-end
-
--- Copy files to the correct places in the TDS tree
-function copytds()
-  local function install(source, dest, files, tool)
-    local moduledir = moduledir
-    -- For material associated with secondary tools (BibTeX, MakeIndex)
-    -- the structure needed is slightly different from those items going
-    -- into the tex/doc/source trees
-    if tool then
-      -- "base" is reserved for the tools themselves: make the assumption
-      -- in this case that the tdsroot name is the right place for stuff to
-      -- go (really just for the team)
-      if module == "base" then
-        moduledir = tdsroot
-      else
-        moduledir = module
-      end
-    end
-    -- Convert the file table(s) to a list of individual files
-    local filenames = { }
-    for _,i in ipairs(files) do
-      for _,j in ipairs(i) do
-        for _,k in ipairs(filelist(source, j)) do
-          insert(filenames, k)
-        end
-      end
-    end
-    -- The target is only created if there are actual files to install
-    if next(filenames) ~= nil then
-      local installdir = tdsdir .. "/" .. dest .. "/" .. moduledir
-      mkdir(installdir)
-      for _,i in ipairs(filenames) do
-        cp(i, source, installdir)
-      end
-    end
-  end
-  install(
-    ".",
-    "doc",
-    {bibfiles, demofiles, docfiles, pdffiles, textfiles, typesetlist}
-  )
-  install(unpackdir, "makeindex", {makeindexfiles}, true)
-  install(unpackdir, "bibtex/bst", {bstfiles}, true)
-  install(".", "source", {sourcelist})
-  install(unpackdir, "tex", {installfiles})
-end
-
--- Unpack files needed to support testing/typesetting/unpacking
-function depinstall(deps)
-  local errorlevel
-  for _,i in ipairs(deps) do
-    print("Installing dependency: " .. i)
-    errorlevel = run(i, "texlua " .. scriptname .. " unpack -q")
-    if errorlevel ~= 0 then
-      return errorlevel
-    end
-  end
-  return 0
-end
-
--- Convert the raw log file into one for comparison/storage: keeps only
--- the 'business' part from the tests and removes system-dependent stuff
-local function formatlog(logfile, newfile, engine)
-  local maxprintline = maxprintline
-  if engine == "luatex" or engine == "luajittex" then
-    maxprintline = maxprintline + 1 -- Deal with an out-by-one error
-  end
-  local function killcheck(line)
-      -- Skip lines containing file dates
-      if match(line, "[^<]%d%d%d%d/%d%d/%d%d") then
-        return true
-      elseif
-      -- Skip \openin/\openout lines in web2c 7.x
-      -- As Lua doesn't allow "(in|out)", a slightly complex approach:
-      -- do a substitution to check the line is exactly what is required!
-        match(
-          gsub(line, "^\\openin", "\\openout"), "^\\openout%d%d? = "
-        ) then
-        return true
-      end
-    return false
-  end
-    -- Substitutions to remove some non-useful changes
-  local function normalize(line, lastline)
-    -- Zap line numbers from \show, \showbox, \box_show and the like:
-    -- do this before wrapping lines
-    line = gsub(line, "^l%.%d+ ", "l. ...")
-    -- Also from lua stack traces.
-    line = gsub(line, "lua:%d+: in function", "lua:...: in function")
-    -- Allow for wrapped lines: preserve the content and wrap
-    -- Skip lines that have an explicit marker for truncation
-    if len(line) == maxprintline  and
-       not match(line, "%.%.%.$") then
-      return "", (lastline or "") .. line
-    end
-    local line = (lastline or "") .. line
-    lastline = ""
-    -- Zap ./ at begin of filename
-    line = gsub(line, "%(%.%/", "(")
-    -- Zap paths if places other than 'here' are accessible
-    if checksearch then
-      -- The pattern excludes < and > as the image part can have
-      -- several entries on one line
-      local pattern = "%w?:?/[^ %<%>]*/([^/%(%)]*%.%w*)"
-      -- Files loaded from TeX: all start ( -- )
-      line = gsub(line, "%(" .. pattern, "(../%1")
-      -- Images
-      line = gsub(line, "<" .. pattern .. ">", "<../%1>")
-      -- luaotfload files start with keywords
-      line = gsub(line, "from " .. pattern .. "%(", "from. ./%1(")
-      line = gsub(line, ": " .. pattern .. "%)", ": ../%1)")
-    end
-    -- Deal with the fact that "(.aux)" may have still a leading space
-    line = gsub(line, "^ %(%.aux%)", "(.aux)")
-    -- Merge all of .fd data into one line so will be removed later
-    if match(line, "^ *%([%.%/%w]+%.fd[^%)]*$") then
-      lastline = (lastline or "") .. line
-      return "", (lastline or "") .. line
-    end
-    -- TeX90/XeTeX knows only the smaller set of dimension units
-    line = gsub(
-      line,
-      "cm, mm, dd, cc, bp, or sp", "cm, mm, dd, cc, nd, nc, bp, or sp"
-    )
-    -- Normalise a case where fixing a TeX bug changes the message text
-    line = gsub(line, "\\csname\\endcsname ", "\\csname\\endcsname")
-    -- Zap "on line <num>" and replace with "on line ..."
-    -- Two similar cases, Lua patterns mean we need to do them separately
-    line = gsub(line, "on line %d*", "on line ...")
-    line = gsub(line, "on input line %d*", "on input line ...")
-    -- Tidy up to ^^ notation
-    for i = 0, 31 do
-      line = gsub(line, char(i), "^^" .. char(64 + i))
-    end
-    -- Remove 'normal' direction information on boxes with (u)pTeX
-    line = gsub(line, ",? yoko direction,?", "")
-    line = gsub(line, ",? yoko%(math%) direction,?", "")
-    -- Remove the \special line that in DVI mode keeps PDFs comparable
-    if match(line, "^%.*\\special%{pdf: docinfo << /Creator") then
-      return ""
-    end
-    -- Remove the \special line possibly present in DVI mode for paper size
-    if match(line, "^%.*\\special%{papersize") then
-      return ""
-    end
-    -- Remove ConTeXt stuff
-    if match(line, "^backend         >") or
-       match(line, "^close source    >") or
-       match(line, "^mkiv lua stats  >") or
-       match(line, "^pages           >") or
-       match(line, "^system          >") or
-       match(line, "^used file       >") or
-       match(line, "^used option     >") or
-       match(line, "^used structure  >") then
-       return ""
-    end
-    -- A tidy-up to keep LuaTeX and other engines in sync
-    line = gsub(line, utf8_char(127), "^^?")
-    -- Unicode engines display chars in the upper half of the 8-bit range:
-    -- tidy up to match pdfTeX if an ASCII engine is in use
-    if next(asciiengines) then
-      for i = 128, 255 do
-        line = gsub(line, utf8_char(i), "^^" .. format("%02x", i))
-      end
-    end
-    return line, lastline
-  end
-  local lastline = ""
-  local newlog = ""
-  local prestart = true
-  local skipping = false
-  -- Read the entire log file as a binary: deals with ^@/^[, etc.
-  local file = assert(open(logfile, "rb"))
-  local contents = gsub(file:read("*all") .. "\n", "\r\n", "\n")
-  close(file)
-  for line in gmatch(contents, "([^\n]*)\n") do
-    if line == "START-TEST-LOG" then
-      prestart = false
-    elseif line == "END-TEST-LOG" then
-      break
-    elseif line == "OMIT" then
-      skipping = true
-    elseif match(line, "^%)?TIMO$") then
-      skipping = false
-    elseif not prestart and not skipping then
-      line, lastline = normalize(line, lastline)
-      if not match(line, "^ *$") and not killcheck(line) then
-        newlog = newlog .. line .. os_newline
-      end
-    end
-  end
-  local newfile = open(newfile, "w")
-  output(newfile)
-  write(newlog)
-  close(newfile)
-end
-
--- Additional normalization for LuaTeX
-local function formatlualog(logfile, newfile)
-  local function normalize(line, lastline, dropping)
-    -- Find \discretionary or \whatsit lines:
-    -- These may come back later
-    if match(line, "^%.+\\discretionary$")                or
-       match(line, "^%.+\\discretionary %(penalty 50%)$") or
-       match(line, "^%.+\\discretionary50%|$")            or
-       match(line, "^%.+\\discretionary50%| replacing $") or
-       match(line, "^%.+\\whatsit$")                      then
-      return "", line
-    end
-    -- For \mathon, we always need this line but the next
-    -- may be affected
-    if match(line, "^%.+\\mathon$") then
-      return line, line
-    end
-    -- LuaTeX has a flexible output box
-    line = gsub(line,"\\box\\outputbox", "\\box255")
-    -- LuaTeX identifies spaceskip glue
-    line = gsub(line,"%(\\spaceskip%) ", " ")
-    -- Remove 'display' at end of display math boxes:
-    -- LuaTeX omits this as it includes direction in all cases
-    line = gsub(line, "(\\hbox%(.*), display$", "%1")
-    -- Remove 'normal' direction information on boxes:
-    -- any bidi/vertical stuff will still show
-    line = gsub(line, ", direction TLT", "")
-    -- Find glue setting and round out the last place
-    local function round_digits(l, m)
-      return gsub(
-        l,
-        m .. " (%-?)%d+%.%d+",
-        m .. " %1"
-          .. format(
-            "%.3f",
-            match(line, m .. " %-?(%d+%.%d+)") or 0
-          )
-      )
-    end
-    if match(line, "glue set %-?%d+%.%d+") then
-      line = round_digits(line, "glue set")
-    end
-    if match(
-        line, "glue %-?%d+%.%d+ plus %-?%d+%.%d+ minus %-?%d+%.%d+$"
-      )
-      then
-      line = round_digits(line, "glue")
-      line = round_digits(line, "plus")
-      line = round_digits(line, "minus")
-    end
-    -- LuaTeX writes ^^M as a new line, which we lose
-    line = gsub(line, "%^%^M", "")
-    -- Remove U+ notation in the "Missing character" message
-    line = gsub(
-        line,
-        "Missing character: There is no (%^%^..) %(U%+(....)%)",
-        "Missing character: There is no %1"
-      )
-    -- A function to handle the box prefix part
-    local function boxprefix(s)
-      return gsub(match(s, "^(%.+)"), "%.", "%%.")
-    end
-    -- 'Recover' some discretionary data
-    if match(lastline, "^%.+\\discretionary %(penalty 50%)$") and
-       match(line, boxprefix(lastline) .. "%.= ") then
-       return gsub(line, "%.= ", ""),""
-    end
-    -- Where the last line was a discretionary, looks for the
-    -- info one level in about what it represents
-    if match(lastline, "^%.+\\discretionary$")                or
-       match(lastline, "^%.+\\discretionary %(penalty 50%)$") or
-       match(lastline, "^%.+\\discretionary50%|$")            or
-       match(lastline, "^%.+\\discretionary50%| replacing $") then
-      local prefix = boxprefix(lastline)
-      if match(line, prefix .. "%.") or
-         match(line, prefix .. "%|") then
-         if match(lastline, " replacing $") and
-            not dropping then
-           -- Modify the return line
-           return gsub(line, "^%.", ""), lastline, true
-         else
-           return "", lastline, true
-         end
-      else
-        if dropping then
-          -- End of a \discretionary block
-          return line, ""
-        else
-          -- Not quite a normal discretionary
-          if match(lastline, "^%.+\\discretionary50%|$") then
-            lastline =  gsub(lastline, "50%|$", "")
-          end
-          -- Remove some info that TeX90 lacks
-          lastline = gsub(lastline, " %(penalty 50%)$", "")
-          -- A normal (TeX90) discretionary:
-          -- add with the line break reintroduced
-          return lastline .. os_newline .. line, ""
-        end
-      end
-    end
-    -- Look for another form of \discretionary, replacing a "-"
-    pattern = "^%.+\\discretionary replacing *$"
-    if match(line, pattern) then
-      return "", line
-    else
-      if match(lastline, pattern) then
-        local prefix = boxprefix(lastline)
-        if match(line, prefix .. "%.\\kern") then
-          return gsub(line, "^%.", ""), lastline, true
-        elseif dropping then
-          return "", ""
-        else
-          return lastline .. os_newline .. line, ""
-        end
-      end
-    end
-    -- For \mathon, if the current line is an empty \hbox then
-    -- drop it
-    if match(lastline, "^%.+\\mathon$") then
-      local prefix = boxprefix(lastline)
-      if match(line, prefix .. "\\hbox%(0%.0%+0%.0%)x0%.0$") then
-        return "", ""
-      end
-    end
-    -- Various \local... things that other engines do not do:
-    -- Only remove the no-op versions
-    if match(line, "^%.+\\localpar$")                or
-       match(line, "^%.+\\localinterlinepenalty=0$") or
-       match(line, "^%.+\\localbrokenpenalty=0$")    or
-       match(line, "^%.+\\localleftbox=null$")       or
-       match(line, "^%.+\\localrightbox=null$")      then
-       return "", ""
-    end
-    -- Older LuaTeX versions set the above up as a whatsit
-    -- (at some stage this can therefore go)
-    if match(lastline, "^%.+\\whatsit$") then
-      local prefix = boxprefix(lastline)
-      if match(line, prefix .. "%.") then
-        return "", lastline, true
-      else
-        -- End of a \whatsit block
-        return line, ""
-      end
-    end
-    -- Wrap some cases that can be picked out
-    -- In some places LuaTeX does use max_print_line, then we
-    -- get into issues with different wrapping approaches
-    if len(line) == maxprintline then
-      return "", lastline .. line
-    elseif len(lastline) == maxprintline then
-      if match(line, "\\ETC%.%}$") then
-        -- If the line wrapped at \ETC we might have lost a space
-        return lastline
-          .. ((match(line, "^\\ETC%.%}$") and " ") or "")
-          .. line, ""
-      elseif match(line, "^%}%}%}$") then
-        return lastline .. line, ""
-      else
-        return lastline .. os_newline .. line, ""
-      end
-    -- Return all of the text for a wrapped (multi)line
-    elseif len(lastline) > maxprintline then
-      return lastline .. line, ""
-    end
-    -- Remove spaces at the start of lines: deals with the fact that LuaTeX
-    -- uses a different number to the other engines
-    return gsub(line, "^%s+", ""), ""
-  end
-  local newlog = ""
-  local lastline = ""
-  local dropping = false
-  -- Read the entire log file as a binary: deals with ^@/^[, etc.
-  local file = assert(open(logfile, "rb"))
-  local contents = gsub(file:read("*all") .. "\n", "\r\n", "\n")
-  close(file)
-  for line in gmatch(contents, "([^\n]*)\n") do
-    line, lastline, dropping = normalize(line, lastline, dropping)
-    if not match(line, "^ *$") then
-      newlog = newlog .. line .. os_newline
-    end
-  end
-  local newfile = open(newfile, "w")
-  output(newfile)
-  write(newlog)
-  close(newfile)
-end
-
--- Look for files, directory by directory, and return the first existing
-function locate(dirs, names)
-  for _,i in ipairs(dirs) do
-    for _,j in ipairs(names) do
-      local path = i .. "/" .. j
-      if fileexists(path) then
-        return path
-      end
-    end
-  end
-end
-
--- List all modules
-function listmodules()
-  local modules = { }
-  local exclmodules = exclmodules or { }
-  for entry in lfs_dir(".") do
-    if entry ~= "." and entry ~= ".." then
-      local attr = lfs_attributes(entry)
-      assert(type(attr) == "table")
-      if attr.mode == "directory" then
-        if not exclmodules[entry] then
-          insert(modules, entry)
-        end
-      end
-    end
-  end
-  return modules
-end
-
--- Run one test which may have multiple engine-dependent comparisons
--- Should create a difference file for each failed test
-function runcheck(name, hide)
-  local checkengines = checkengines
-  if optengines then
-    checkengines = optengines
-  end
-  local errorlevel = 0
-  for _,i in ipairs(checkengines) do
-    -- Allow for luatex == luajittex for .tlg purposes
-    local engine = i
-    if i == "luajittex" then
-      engine = "luatex"
-    end
-    checkpdf = setup_check(name, engine)
-    runtest(name, i, hide, lvtext, checkpdf)
-    -- Generation of results depends on test type
-    local errlevel
-    if checkpdf then
-      errlevel = compare_pdf(name, engine)
-    else
-      errlevel = compare_tlg(name, engine)
-    end
-    if errlevel ~= 0 and opthalt then
-      showfaileddiff()
-      if errlevel ~= 0 then
-        return 1
-      end
-    end
-    if errlevel > errorlevel then
-      errorlevel = errlevel
-    end
-  end
-  return errorlevel
-end
-
-function setup_check(name, engine)
-  local testname = name .. "." .. engine
-  local pdffile = locate(
-    {testfiledir, unpackdir},
-    {testname .. pdfext, name .. pdfext}
-  )
-  local tlgfile = locate(
-    {testfiledir, unpackdir},
-    {testname .. tlgext, name .. tlgext}
-  )
-  -- Attempt to generate missing reference file from expectation
-  if not (pdffile or tlgfile) then
-    if not locate({unpackdir, testfiledir}, {name .. lveext}) then
-      print(
-        "Error: failed to find " .. pdfext .. ", " .. tlgext .. " or "
-          .. lveext .. " file for " .. name .. "!"
-      )
-      exit(1)
-    end
-    runtest(name, engine, true, lveext, true)
-    pdffile = testdir .. "/" .. testname .. pdfext
-    -- If a PDF is generated use it for comparisons
-    if not fileexists(pdffile) then
-      pdffile = nil
-      ren(testdir, testname .. logext, testname .. tlgext)
-    end
-  else
-    -- Install comparison files found
-    for _,v in pairs({pdffile, tlgfile}) do
-      if v then
-        cp(
-          match(v, ".*/(.*)"),
-          match(v, "(.*)/.*"),
-          testdir
-        )
-      end
-    end
-  end
-  if pdffile then
-    local pdffile = match(pdffile, ".*/(.*)")
-    ren(
-      testdir,
-      pdffile,
-      gsub(pdffile, pdfext .. "$", ".ref" .. pdfext)
-    )
-    return true
-  else
-    return false
-  end
-end
-
-function compare_pdf(name, engine)
-  local errorlevel
-  local testname = name .. "." .. engine
-  local cmpfile    = testdir .. "/" .. testname .. os_cmpext
-  local pdffile    = testdir .. "/" .. testname .. pdfext
-  local refpdffile = locate(
-    {testdir}, {testname .. ".ref" .. pdfext, name .. ".ref" .. pdfext}
-  )
-  if not refpdffile then
-    return
-  end
-  if os_type == "windows" then
-    refpdffile = unix_to_win(refpdffile)
-  end
-  errorlevel = execute(
-    os_cmpexe .. " " .. refpdffile .. " " .. pdffile .. " > " .. cmpfile
-  )
-  if errorlevel == 0 then
-    os_remove(cmpfile)
-  end
-  return errorlevel
-end
-
-function compare_tlg(name, engine)
-  local errorlevel
-  local testname = name .. "." .. engine
-  local difffile = testdir .. "/" .. testname .. os_diffext
-  local logfile  = testdir .. "/" .. testname .. logext
-  local tlgfile  = locate({testdir}, {testname .. tlgext, name .. tlgext})
-  if not tlgfile then
-    return
-  end
-  if os_type == "windows" then
-    tlgfile = unix_to_win(tlgfile)
-  end
-  -- Do additional log formatting if the engine is LuaTeX, there is no
-  -- LuaTeX-specific .tlg file and the default engine is not LuaTeX
-  if engine == "luatex"
-    and not match(tlgfile, "%.luatex" .. "%" .. tlgext)
-    and stdengine ~= "luatex"
-    and stdengine ~= "luajittex"
-    then
-    local luatlgfile = testdir .. "/" .. name .. ".luatex" ..  tlgext
-    if os_type == "windows" then
-      luatlgfile = unix_to_win(luatlgfile)
-    end
-    formatlualog(tlgfile, luatlgfile)
-    formatlualog(logfile, logfile)
-    -- This allows code sharing below: we only need the .tlg name in one place
-    tlgfile = luatlgfile
-  end
-  errorlevel = execute(
-    os_diffexe .. " " .. tlgfile .. " " .. logfile .. " > " .. difffile
-  )
-  if errorlevel == 0 then
-    os_remove(difffile)
-  end
-  return errorlevel
-end
-
--- Run one of the test files: doesn't check the result so suitable for
--- both creating and verifying .tlg files
-function runtest(name, engine, hide, ext, makepdf)
-  local lvtfile = name .. (ext or lvtext)
-  cp(lvtfile, fileexists(testfiledir .. "/" .. lvtfile)
-    and testfiledir or unpackdir, testdir)
-  local engine = engine or stdengine
-  -- Set up the format file name if it's one ending "...tex"
-  local realengine = engine
-  local format
-  if
-    match(checkformat, "tex$") and
-    not match(engine, checkformat) then
-    format = " -fmt=" .. gsub(engine, "(.*)tex$", "%1") .. checkformat
-  else
-    format = ""
-  end
-  -- Special casing for e-LaTeX format
-  if
-    match(checkformat, "^latex$") and
-    match(engine, "^etex$") then
-    format = " -fmt=latex"
-  end
-  -- Special casing for (u)pTeX LaTeX formats
-  if
-    match(checkformat, "^latex$") and
-    match(engine, "^u?ptex$") then
-    realengine = "e" .. engine
-  end
-  -- Special casing for XeTeX engine
-  local checkopts = checkopts
-  if match(engine, "xetex") and not makepdf then
-    checkopts = checkopts .. " -no-pdf"
-  end
-  -- Special casing for ConTeXt
-  if match(checkformat, "^context$") then
-    format = ""
-    if engine == "luatex" or engine == "luajittex" then
-      realengine = "context"
-    elseif engine == "pdftex" then
-      realengine = "texexec"
-    elseif engine == "xetex" then
-      realengine = "texexec --xetex"
-    else
-      print("Engine incompatible with format")
-      exit(1)
-    end
-  end
-  local logfile = testdir .. "/" .. name .. logext
-  local newfile = testdir .. "/" .. name .. "." .. engine .. logext
-  local asciiopt = ""
-  for _,i in ipairs(asciiengines) do
-    if realengine == i then
-      asciiopt = "-translate-file ./ascii.tcx "
-      break
-    end
-  end
-  for i = 1, checkruns do
-    run(
-      testdir,
-      -- No use of localdir here as the files get copied to testdir:
-      -- avoids any paths in the logs
-      os_setenv .. " TEXINPUTS=." .. (checksearch and os_pathsep or "")
-        .. os_concat ..
-      -- Avoid spurious output from (u)pTeX
-      os_setenv .. " GUESS_INPUT_KANJI_ENCODING=0"
-        .. os_concat ..
-      -- Fix the time of the run
-      os_setenv .. " SOURCE_DATE_EPOCH=" .. epoch
-        .. os_concat ..
-      os_setenv .. " SOURCE_DATE_EPOCH_TEX_PRIMITIVES=1"
-        .. os_concat ..
-      -- Ensure lines are of a known length
-      os_setenv .. " max_print_line=" .. maxprintline
-        .. os_concat ..
-      realengine ..  format .. " "
-        .. checkopts .. " " .. asciiopt .. lvtfile
-        .. (hide and (" > " .. os_null) or "")
-        .. os_concat ..
-      runtest_tasks(jobname(lvtfile))
-    )
-  end
-  if makepdf and fileexists(testdir .. "/" .. name .. dviext) then
-    dvitopdf(name, testdir, engine, hide)
-  end
-  formatlog(logfile, newfile, engine)
-  -- Store secondary files for this engine
-  for _,i in ipairs(filelist(testdir, name .. ".???")) do
-    local ext = match(i, "%....")
-    if ext ~= lvtext and ext ~= tlgext and ext ~= lveext and ext ~= logext then
-      if not fileexists(testsuppdir .. "/" .. i) then
-        ren(
-          testdir, i, gsub(
-            i, gsub(name, "%-", "%%-"), name .. "." .. engine
-          )
-        )
-      end
-    end
-  end
-end
-
--- A hook to allow additional tasks to run for the tests
-runtest_tasks = runtest_tasks or function(name)
-  return ""
-end
-
-function dvitopdf(name, dir, engine, hide)
-  if match(engine, "^u?ptex$") then
-    run(
-      dir,
-      os_setenv .. " SOURCE_DATE_EPOCH=" .. epoch
-        .. os_concat ..
-     "dvipdfmx  " .. name .. dviext
-       .. (hide and (" > " .. os_null) or "")
-    )
-  else
-    run(
-      dir,
-      os_setenv .. " SOURCE_DATE_EPOCH=" .. epoch
-        .. os_concat ..
-     "dvips " .. name .. dviext
-       .. (hide and (" > " .. os_null) or "")
-       .. os_concat ..
-     "ps2pdf " .. name .. psext
-        .. (hide and (" > " .. os_null) or "")
-    )
-  end
-end
-
--- Split a path into file and directory component
-function splitpath(file)
-  local path, name = match(file, "^(.*)/([^/]*)$")
-  if path then
-    return path, name
-  else
-    return ".", file
-  end
-end
-
--- Arguably clearer names
-function basename(file)
-  return(select(2, splitpath(file)))
-end
-
-function dirname(file)
-  return(select(1, splitpath(file)))
-end
-
--- Strip the extension from a file name (if present)
-function jobname(file)
-  local name = match(select(2, splitpath(file)), "^(.*)%.")
-  return name or file
-end
-
--- Look for a test: could be in the testfiledir or the unpackdir
-function testexists(test)
-  return(locate({testfiledir, unpackdir}, {test .. lvtext}))
-end
-
---
--- Auxiliary functions for typesetting: need to be generally available
---
-
--- An auxiliary used to set up the environmental variables
-function runtool(subdir, dir, envvar, command)
-  dir = dir or "."
-  return(
-    run(
-      typesetdir .. "/" .. subdir,
-      os_setenv .. " " .. envvar .. "=." .. os_pathsep
-        .. abspath(localdir) .. os_pathsep
-        .. abspath(dir .. "/" .. subdir)
-        .. (typesetsearch and os_pathsep or "") ..
-      os_concat ..
-      command
-    )
-  )
-end
-
-function biber(name, dir)
-  if fileexists(typesetdir .. "/" .. name .. ".bcf") then
-    local path, name = splitpath(name)
-    return(
-      runtool(path, dir, "BIBINPUTS",  biberexe .. " " .. biberopts .. " " .. name)
-    )
-  end
-  return 0
-end
-
-function bibtex(name, dir)
-  if fileexists(typesetdir .. "/" .. name .. ".aux") then
-    -- LaTeX always generates an .aux file, so there is a need to
-    -- look inside it for a \citation line
-    local grep
-    if os_type == "windows" then
-      grep = "\\\\"
-    else
-     grep = "\\\\\\\\"
-    end
-    local path, name = splitpath(name)
-    if run(
-        typesetdir,
-        os_grepexe .. " \"^" .. grep .. "citation{\" " .. name .. ".aux > "
-          .. os_null
-      ) + run(
-        typesetdir,
-        os_grepexe .. " \"^" .. grep .. "bibdata{\" " .. name .. ".aux > "
-          .. os_null
-      ) == 0 then
-      return(
-        -- Cheat slightly as we need to set two variables
-        runtool(
-          path, dir,
-          "BIBINPUTS",
-          os_setenv .. " BSTINPUTS=." .. os_pathsep
-            .. abspath(localdir)
-            .. (typesetsearch and os_pathsep or "") ..
-          os_concat ..
-          bibtexexe .. " " .. bibtexopts .. " " .. name
-        )
-      )
-    end
-  end
-  return 0
-end
-
-function makeindex(name, dir, inext, outext, logext, style)
-  if fileexists(typesetdir .. "/" .. name .. inext) then
-    local path, name = splitpath(name)
-    return(
-      runtool(
-        path, dir,
-        "INDEXSTYLE",
-        makeindexexe .. " " .. makeindexopts .. " "
-          .. " -s " .. style .. " -o " .. name .. outext
-          .. " -t " .. name .. " "  .. name .. inext
-      )
-    )
-  end
-  return 0
-end
-
-function tex(file, dir)
-  local path, name = splitpath(file)
-  return(
-    runtool(
-      path, dir,
-      "TEXINPUTS",
-      typesetexe .. " " .. typesetopts .. " \"" .. typesetcmds
-        .. "\\input " .. name .. "\""
-    )
-  )
-end
-
-function typesetpdf(file, dir)
-  local name = jobname(file)
-  print("Typesetting " .. name)
-  local errorlevel = typeset(file, dir)
-  if errorlevel == 0 then
-    os_remove(name .. ".pdf")
-    cp(name .. ".pdf", typesetdir, ".")
-  else
-    print(" ! Compilation failed")
-  end
-  return errorlevel
-end
-
-typeset = typeset or function(file, dir)
-  dir = dir or "."
-  local errorlevel = tex(file, dir)
-  if errorlevel ~= 0 then
-    return errorlevel
-  else
-    local name = jobname(file)
-    errorlevel = biber(name, dir) + bibtex(name, dir)
-    if errorlevel == 0 then
-      local function cycle(name, dir)
-        return(
-          makeindex(name, dir, ".glo", ".gls", ".glg", glossarystyle) +
-          makeindex(name, dir, ".idx", ".ind", ".ilg", indexstyle)    +
-          tex(file, dir)
-        )
-      end
-      errorlevel = cycle(name, dir)
-      if errorlevel == 0 then
-        errorlevel = cycle(name, dir)
-      end
-    end
-    return errorlevel
-  end
-end
-
--- Standard versions of the main targets for building modules
-
--- Simply print out how to use the build system
-function help()
-  print("usage: " .. arg[0] .. " <command> [<options>] [<names>]")
-  print("")
-  print("The most commonly used l3build commands are:")
-  if testfiledir ~= "" then
-    print("   check      Run all automated tests")
-  end
-  print("   clean      Clean out directory tree")
-  if next(cmdchkfiles) ~= nil then
-    print("   cmdcheck   Check commands documented are defined")
-  end
-  if module == "" or bundle == "" then
-    print("   ctan       Create CTAN-ready archive")
-  end
-  print("   doc        Typesets all documentation files")
-  print("   install    Installs files into the local texmf tree")
-  if module ~= "" and testfiledir ~= "" then
-    print("   save       Saves test validation log")
-  end
-  print("   setversion Update version information in sources")
-  print("")
-  print("Valid options are:")
-  print("   --date|-d           Sets the date to insert into sources")
-  print("   --engine|-e         Sets the engine to use for running test")
-  print("   --halt-on-error|-H  Stops running tests after the first failure")
-  print("   --pdf|-p            Check/save PDF files")
-  print("   --quiet|-q          Suppresses TeX output when unpacking")
-  print("   --release|-r        Sets the release to insert into sources")
-  print("   --testfiledir|-t    Selects the specified testfile location")
-  print("")
-  print("See l3build.pdf for further details.")
-end
-
-function check(names)
-  local errorlevel = 0
-  if testfiledir ~= "" and direxists(testfiledir) then
-    checkinit()
-    local hide = true
-    if names and next(names) then
-      hide = false
-    end
-    names = names or { }
-    -- No names passed: find all test files
-    if not next(names) then
-      for _,i in pairs(filelist(testfiledir, "*" .. lvtext)) do
-        insert(names, jobname(i))
-      end
-      for _,i in ipairs(filelist(unpackdir, "*" .. lvtext)) do
-        if fileexists(testfiledir .. "/" .. i) then
-          print("Duplicate test file: " .. i)
-          return 1
-        else
-          insert(names, jobname(i))
-        end
-      end
-    end
-    -- Actually run the tests
-    print("Running checks on")
-    for _,name in ipairs(names) do
-      print("  " .. name)
-      local errlevel = runcheck(name, hide)
-      -- Return value must be 1 not errlevel
-      if errlevel ~= 0 then
-        if opthalt then
-          return 1
-        else
-          errorlevel = 1
-        end
-      end
-    end
-    if errorlevel ~= 0 then
-      checkdiff()
-    else
-      print("\n  All checks passed\n")
-    end
-  end
-  return errorlevel
-end
-
--- A short auxiliary to print the list of differences for check
-function checkdiff()
-  print("\n  Check failed with difference files")
-  for _,i in ipairs(filelist(testdir, "*" .. os_diffext)) do
-    print("  - " .. testdir .. "/" .. i)
-  end
-  for _,i in ipairs(filelist(testdir, "*" .. os_cmpext)) do
-    print("  - " .. testdir .. "/" .. i)
-  end
-  print("")
-end
-
-function showfaileddiff()
-  print("\nCheck failed with difference file")
-  for _,i in ipairs(filelist(testdir, "*" .. os_diffext)) do
-    print("  - " .. testdir .. "/" .. i)
-    print("")
-    local f = open(testdir .. "/" .. i,"r")
-    local content = f:read("*all")
-    f:close()
-    print("-----------------------------------------------------------------------------------")
-    print(content)
-    print("-----------------------------------------------------------------------------------")
-  end
-  for _,i in ipairs(filelist(testdir, "*" .. os_cmpext)) do
-    print("  - " .. testdir .. "/" .. i)
-  end
-end
-
--- Remove all generated files
-function clean()
-  -- To make sure that distribdir never contains any stray subdirs,
-  -- it is entirely removed then recreated rather than simply deleting
-  -- all of the files
-  local errorlevel =
-    rmdir(distribdir)    +
-    mkdir(distribdir)    +
-    cleandir(localdir)   +
-    cleandir(testdir)    +
-    cleandir(typesetdir) +
-    cleandir(unpackdir)
-  for _,i in ipairs(cleanfiles) do
-    errorlevel = rm(".", i) + errorlevel
-  end
-  return errorlevel
-end
-
-function bundleclean()
-  local errorlevel = allmodules("clean")
-  for _,i in ipairs(cleanfiles) do
-    errorlevel = rm(".", i) + errorlevel
-  end
-  return (
-    errorlevel     +
-    rmdir(ctandir) +
-    rmdir(tdsdir)
-  )
-end
-
--- Check commands are defined
-function cmdcheck()
-  mkdir(localdir)
-  cleandir(testdir)
-  depinstall(checkdeps)
-  for _,i in ipairs({bibfiles, docfiles, sourcefiles, typesetfiles}) do
-    for _,j in ipairs(i) do
-      cp(j, ".", testdir)
-    end
-  end
-  for _,i in ipairs(typesetsuppfiles) do
-    cp(i, supportdir, testdir)
-  end
-  local engine = gsub(stdengine, "tex$", "latex")
-  local localdir = abspath(localdir)
-  print("Checking source files")
-  for _,i in ipairs(cmdchkfiles) do
-    for _,j in ipairs(filelist(".", i)) do
-      print("  " .. jobname(j))
-      run(
-        testdir,
-        os_setenv .. " TEXINPUTS=." .. os_pathsep .. localdir
-          .. os_pathsep ..
-        os_concat ..
-        engine .. " " .. cmdchkopts ..
-          " \"\\PassOptionsToClass{check}{l3doc} \\input " .. j .. "\""
-          .. " > " .. os_null
-      )
-      for line in lines(testdir .. "/" .. jobname(j) .. ".cmds") do
-        if match(line, "^%!") then
-          print("   - " .. match(line, "^%! (.*)"))
-        end
-      end
-    end
-  end
-end
-
-function ctan(standalone)
-  -- Always run tests for all engines
-  optengines = nil
-  local function dirzip(dir, name)
-    local zipname = name .. ".zip"
-    local function tab_to_str(table)
-      local string = ""
-      for _,i in ipairs(table) do
-        string = string .. " " .. "\"" .. i .. "\""
-      end
-      return string
-    end
-    -- Convert the tables of files to quoted strings
-    local binfiles = tab_to_str(binaryfiles)
-    local exclude = tab_to_str(excludefiles)
-    -- First, zip up all of the text files
-    run(
-      dir,
-      zipexe .. " " .. zipopts .. " -ll ".. zipname .. " " .. "."
-        .. (
-          (binfiles or exclude) and (" -x" .. binfiles .. " " .. exclude)
-          or ""
-        )
-    )
-    -- Then add the binary ones
-    run(
-      dir,
-      zipexe .. " " .. zipopts .. " -g ".. zipname .. " " .. ". -i" ..
-        binfiles .. (exclude and (" -x" .. exclude) or "")
-    )
-  end
-  local errorlevel
-  if standalone then
-    errorlevel = check()
-    bundle = module
-  else
-    errorlevel = allmodules("bundlecheck")
-  end
-  if errorlevel == 0 then
-    rmdir(ctandir)
-    mkdir(ctandir .. "/" .. ctanpkg)
-    rmdir(tdsdir)
-    mkdir(tdsdir)
-    if standalone then
-      errorlevel = bundlectan()
-    else
-      errorlevel = allmodules("bundlectan")
-    end
-  else
-    print("\n====================")
-    print("Tests failed, zip stage skipped!")
-    print("====================\n")
-    return errorlevel
-  end
-  if errorlevel == 0 then
-    for _,i in ipairs(textfiles) do
-      for _,j in pairs({unpackdir, "."}) do
-        cp(i, j, ctandir .. "/" .. ctanpkg)
-        cp(i, j, tdsdir .. "/doc/" .. tdsroot .. "/" .. bundle)
-      end
-    end
-    dirzip(tdsdir, ctanpkg .. ".tds")
-    if packtdszip then
-      cp(ctanpkg .. ".tds.zip", tdsdir, ctandir)
-    end
-    dirzip(ctandir, ctanpkg)
-    cp(ctanpkg .. ".zip", ctandir, ".")
-  else
-    print("\n====================")
-    print("Typesetting failed, zip stage skipped!")
-    print("====================\n")
-  end
-  return errorlevel
-end
-
-function bundlectan()
-  -- Generate a list of individual file names excluding those in the second
-  -- argument: the latter is a table
-  local function excludelist(include, exclude)
-    local include = include or { }
-    local exclude = exclude or { }
-    local includelist = { }
-    local excludelist = { }
-    for _,i in ipairs(exclude) do
-      for _,j in ipairs(i) do
-        for _,k in ipairs(filelist(".", j)) do
-          excludelist[k] = true
-        end
-      end
-    end
-    for _,i in ipairs(include) do
-      for _,j in ipairs(filelist(".", i)) do
-        if not excludelist[j] then
-          insert(includelist, j)
-        end
-      end
-    end
-    return includelist
-  end
-  unpack()
-  local errorlevel = doc()
-  if errorlevel == 0 then
-    -- Work out what PDF files are available
-    pdffiles = { }
-    for _,i in ipairs(typesetfiles) do
-      insert(pdffiles, (gsub(i, "%.%w+$", ".pdf")))
-    end
-    -- For the purposes here, any typesetting demo files need to be
-    -- part of the main typesetting list
-    local typesetfiles
-    for _,v in pairs(typesetdemofiles) do
-      insert(typesetfiles, v)
-    end
-    typesetlist = excludelist(typesetfiles, {sourcefiles})
-    sourcelist = excludelist(
-      sourcefiles, {bstfiles, installfiles, makeindexfiles}
-    )
-    copyctan()
-    copytds()
-  end
-  return errorlevel
-end
-
--- Typeset all required documents
--- Uses a set of dedicated auxiliaries that need to be available to others
-function doc(files)
-  -- Set up
-  cleandir(typesetdir)
-  for _,i in ipairs(
-    {bibfiles, docfiles, sourcefiles, typesetfiles, typesetdemofiles}
-  ) do
-    for _,j in ipairs(i) do
-      cp(j, ".", typesetdir)
-    end
-  end
-  for _,i in ipairs(typesetsuppfiles) do
-    cp(i, supportdir, typesetdir)
-  end
-  depinstall(typesetdeps)
-  unpack({sourcefiles, typesetsourcefiles})
-  -- Main loop for doc creation
-  for _, typesetfiles in ipairs({typesetdemofiles, typesetfiles}) do
-    for _,i in ipairs(typesetfiles) do
-      for _, dir in ipairs({unpackdir, typesetdir}) do
-        for j,_ in pairs(tree(dir, i)) do
-          -- Allow for command line selection of files
-          local typeset = true
-          if files and next(files) then
-            typeset = false
-            for _,k in ipairs(files) do
-              if k == jobname(j) then
-                typeset = true
-                break
-              end
-            end
-          end
-          if typeset then
-            local errorlevel = typesetpdf(j, dir)
-            if errorlevel ~= 0 then
-              return errorlevel
-            end
-          end
-        end
-      end
-    end
-  end
-  return 0
-end
-
--- Locally install files: only deals with those extracted, not docs etc.
-function install()
-  local errorlevel = unpack()
-  if errorlevel ~= 0 then
-    return errorlevel
-  end
-  set_program_name("latex")
-  local texmfhome = var_value("TEXMFHOME")
-  local installdir = texmfhome .. "/tex/" .. moduledir
-  errorlevel = cleandir(installdir)
-  if errorlevel ~= 0 then
-    return errorlevel
-  end
-  for _,i in ipairs(installfiles) do
-    errorlevel = cp(i, unpackdir, installdir)
-    if errorlevel ~= 0 then
-      return errorlevel
-    end
-  end
-  return 0
-end
-
-function save(names)
-  checkinit()
-  local engines = optengines or {stdengine}
-  for _,name in pairs(names) do
-    local engine
-    for _,engine in pairs(engines) do
-      local tlgengine = ((engine == stdengine and "") or "." .. engine)
-      local tlgfile  = name .. tlgengine .. tlgext
-      local spdffile = name .. tlgengine .. pdfext
-      local newfile  = name .. "." .. engine .. logext
-      local pdffile  = name .. "." .. engine .. pdfext
-      local refext = ((optpdf and pdfext) or tlgext)
-      if testexists(name) then
-        print("Creating and copying " .. refext)
-        runtest(name, engine, false, lvtext, optpdf)
-        if optpdf then
-          ren(testdir, pdffile, spdffile)
-          cp(spdffile, testdir, testfiledir)
-        else
-          ren(testdir, newfile, tlgfile)
-          cp(tlgfile, testdir, testfiledir)
-        end
-        if fileexists(unpackdir .. "/" .. tlgfile) then
-          print(
-            "Saved " .. tlgext
-              .. " file overrides unpacked version of the same name"
-          )
-        end
-      elseif locate({unpackdir, testfiledir}, {name .. lveext}) then
-        print(
-          "Saved " .. tlgext .. " file overrides a "
-            .. lveext .. " file of the same name"
-        )
-      else
-        print(
-          "Test input \"" .. testfiledir .. "/" .. name .. lvtext
-            .. "\" not found"
-        )
-      end
-    end
-  end
-end
-
--- Provide some standard search-and-replace functions
-if versionform ~= "" and not setversion_update_line then
-  if versionform == "ProvidesPackage" then
-    function setversion_update_line(line, date, release)
-      -- No real regex so do it one type at a time
-      for _,i in pairs({"Class", "File", "Package"}) do
-        if match(
-          line,
-          "^\\Provides" .. i .. "{[a-zA-Z0-9%-%.]+}%[[^%]]*%]$"
-        ) then
-          line = gsub(line, "%[%d%d%d%d/%d%d/%d%d", "["
-            .. gsub(date, "%-", "/"))
-          line = gsub(
-            line, "(%[%d%d%d%d/%d%d/%d%d) [^ ]*", "%1 " .. release
-          )
-          break
-        end
-      end
-      return line
-    end
-  elseif versionform == "ProvidesExplPackage" then
-    function setversion_update_line(line, date, release)
-      -- No real regex so do it one type at a time
-      for _,i in pairs({"Class", "File", "Package"}) do
-        if match(
-          line,
-          "^\\ProvidesExpl" .. i .. " *{[a-zA-Z0-9%-%.]+}"
-        ) then
-          line = gsub(
-            line,
-            "{%d%d%d%d/%d%d/%d%d}( *){[^}]*}",
-            "{" .. gsub(date, "%-", "/") .. "}%1{" .. release .. "}"
-          )
-          break
-        end
-      end
-      return line
-    end
-  elseif versionform == "filename" then
-    function setversion_update_line(line, date, release)
-      if match(line, "^\\def\\filedate{%d%d%d%d/%d%d/%d%d}$") then
-        line = "\\def\\filedate{" .. gsub(date, "%-", "/") .. "}"
-      end
-      if match(line, "^\\def\\fileversion{[^}]+}$") then
-        line = "\\def\\fileversion{" .. release .. "}"
-      end
-      return line
-    end
-  elseif versionform == "ExplFileDate" then
-    function setversion_update_line(line, date, release)
-      if match(line, "^\\def\\ExplFileDate{%d%d%d%d/%d%d/%d%d}$") then
-        line = "\\def\\ExplFileDate{" .. gsub(date, "%-", "/") .. "}"
-      end
-      if match(line, "^\\def\\ExplFileVersion{[^}]+}$") then
-        line = "\\def\\ExplFileVersion{" .. release .. "}"
-      end
-      return line
-    end
-  end
-end
-
--- Used to actually carry out search-and-replace
-setversion_update_line = setversion_update_line or function(line, date, release)
-  return line
-end
-
-function setversion(dir)
-  local function rewrite(dir, file, date, release)
-    local changed = false
-    local result = ""
-    for line in lines(dir .. "/" .. file) do
-      local newline = setversion_update_line(line, date, release)
-      if newline ~= line then
-        line = newline
-        changed = true
-      end
-      result = result .. line .. os_newline
-    end
-    if changed then
-      -- Avoid adding/removing end-of-file newline
-      local f = open(dir .. "/" .. file, "rb")
-      local content = f:read("*all")
-      close(f)
-      if not match(content, os_newline .. "$") then
-        gsub(result, os_newline .. "$", "")
-      end
-      -- Write the new file
-      ren(dir, file, file .. bakext)
-      local f = open(dir .. "/" .. file, "w")
-      output(f)
-      write(result)
-      close(f)
-      rm(dir, file .. bakext)
-    end
-  end
-  local date = os_date("%Y-%m-%d")
-  if optdate then
-    date = optdate[1] or date
-  end
-  local release = -1
-  if optrelease then
-    release = optrelease[1] or release
-  end
-  local dir = dir or "."
-  for _,i in pairs(versionfiles) do
-    for _,j in pairs(filelist(dir, i)) do
-      rewrite(dir, j, date, release)
-    end
-  end
-  return 0
-end
-
--- Unpack the package files using an 'isolated' system: this requires
--- a copy of the 'basic' DocStrip program, which is used then removed
-function unpack(sources)
-  local errorlevel = depinstall(unpackdeps)
-  if errorlevel ~= 0 then
-    return errorlevel
-  end
-  errorlevel = bundleunpack({"."}, sources)
-  if errorlevel ~= 0 then
-    return errorlevel
-  end
-  for _,i in ipairs(installfiles) do
-    errorlevel = cp(i, unpackdir, localdir)
-    if errorlevel ~= 0 then
-      return errorlevel
-    end
-  end
-  return 0
-end
-
--- Split off from the main unpack so it can be used on a bundle and not
--- leave only one modules files
-bundleunpack = bundleunpack or function(sourcedir, sources)
-  local errorlevel = mkdir(localdir)
-  if errorlevel ~=0 then
-    return errorlevel
-  end
-  errorlevel = cleandir(unpackdir)
-  if errorlevel ~=0 then
-    return errorlevel
-  end
-  for _,i in ipairs(sourcedir or {"."}) do
-    for _,j in ipairs(sources or {sourcefiles}) do
-      for _,k in ipairs(j) do
-        errorlevel = cp(k, i, unpackdir)
-        if errorlevel ~=0 then
-          return errorlevel
-        end
-      end
-    end
-  end
-  for _,i in ipairs(unpacksuppfiles) do
-    errorlevel = cp(i, supportdir, localdir)
-    if errorlevel ~=0 then
-      return errorlevel
-    end
-  end
-  for _,i in ipairs(unpackfiles) do
-    for j,_ in pairs(tree(unpackdir, i)) do
-      -- This 'yes' business is needed to pass a series of "y\n" to
-      -- TeX if \askforoverwrite is true
-      -- That is all done using a file as it's the only way on Windows and
-      -- on Unix the "yes" command can't be used inside execute (it never
-      -- stops, which confuses Lua)
-      execute(os_yes .. ">>" .. localdir .. "/yes")
-      local path, name = splitpath(j)
-      local localdir = abspath(localdir)
-      errorlevel = run(
-        unpackdir .. "/" .. path,
-        os_setenv .. " TEXINPUTS=." .. os_pathsep
-          .. localdir .. (unpacksearch and os_pathsep or "") ..
-        os_concat ..
-        unpackexe .. " " .. unpackopts .. " " .. name .. " < "
-          .. localdir .. "/yes"
-          .. (optquiet and (" > " .. os_null) or "")
-      )
-      if errorlevel ~=0 then
-        return errorlevel
-      end
-    end
-  end
-  return 0
-end
-
-function version()
-  print(
-    "\n"
-    .. "l3build Release " .. gsub(release_date, "/", "-") .. "\n"
-  )
-end
-
---
--- The overall main function
---
-
-function stdmain(target, files)
-  local errorlevel
-  -- If the module name is empty, the script is running in a bundle:
-  -- apart from ctan all of the targets are then just mappings
-  if module == "" then
-    -- Detect all of the modules
-    modules = modules or listmodules()
-    if target == "doc" then
-      errorlevel = allmodules("doc")
-    elseif target == "check" then
-      errorlevel = allmodules("bundlecheck")
-      if errorlevel ~=0 then
-        print("There were errors: checks halted!\n")
-      end
-    elseif target == "clean" then
-      errorlevel = bundleclean()
-    elseif target == "cmdcheck" and next(cmdchkfiles) ~= nil then
-      errorlevel = allmodules("cmdcheck")
-    elseif target == "ctan" then
-      errorlevel = ctan()
-    elseif target == "install" then
-      errorlevel = allmodules("install")
-    elseif target == "setversion" then
-      errorlevel = allmodules("setversion")
-      -- Deal with any files in the bundle dir itself
-      if errorlevel == 0 then
-        errorlevel = setversion()
-      end
-    elseif target == "unpack" then
-      errorlevel = allmodules("bundleunpack")
-    elseif target == "version" then
-      version()
-    else
-      help()
-    end
-  else
-    if target == "bundleunpack" then -- 'Hidden' as only needed 'higher up'
-      depinstall(unpackdeps)
-      errorlevel = bundleunpack()
-    elseif target == "bundlecheck" then
-      errorlevel = check()
-    elseif target == "bundlectan" then
-      errorlevel = bundlectan()
-    elseif target == "doc" then
-      errorlevel = doc(files)
-    elseif target == "check" then
-      errorlevel = check(files)
-    elseif target == "clean" then
-      errorlevel = clean()
-    elseif target == "cmdcheck" and next(cmdchkfiles) ~= nil then
-      errorlevel = cmdcheck()
-    elseif target == "ctan" and bundle == "" then  -- Stand-alone module
-      errorlevel = ctan(true)
-    elseif target == "install" then
-      errorlevel = install()
-    elseif target == "save" then
-      if next(files) then
-        errorlevel = save(files)
-      else
-        help()
-      end
-    elseif target == "setversion" then
-      errorlevel = setversion()
-    elseif target == "unpack" then
-      errorlevel = unpack()
-    elseif target == "version" then
-      version()
-    else
-      help()
-    end
-  end
-  if errorlevel ~= 0 then
-    exit(1)
-  else
-    exit(0)
-  end
-end
-
--- Allow main function to be disabled 'higher up'
-main = main or stdmain
-
--- Pick up and read any per-run testfiledir
-if options["testfiledir"] then
-  if #options["testfiledir"] == 1 then
-    testfiledir = options["testfiledir"][1]
-    if fileexists(testfiledir .. "/config.lua") then
-      dofile(testfiledir .. "/config.lua")
-    end
-  else
-    print("Cannot use more than one testfile dir at a time!")
-    return 1
-  end
-end
-
--- Call the main function
-main(options["target"], options["files"])
diff --git a/l3build/testfiles-plain/plain-pdftex.lvt b/l3build/testfiles-plain/plain-pdftex.lvt
deleted file mode 100644
index d55ca49..0000000
--- a/l3build/testfiles-plain/plain-pdftex.lvt
+++ /dev/null
@@ -1,18 +0,0 @@
-%&pdftex
-
-\input regression-test.tex\relax
-
-\newtoks\foo % \outer
-
-\START
-
-\ISCFGLOADED
-
-\TEST{\afterassignment}{
-  \def\x{\afterassignment{\edef\y{world}}\foo}
-  \x={hello}
-  \showthe\foo
-  \show\y
-}
-
-\END
diff --git a/l3build/testfiles-plain/plain-pdftex.tlg b/l3build/testfiles-plain/plain-pdftex.tlg
deleted file mode 100644
index f09433e..0000000
--- a/l3build/testfiles-plain/plain-pdftex.tlg
+++ /dev/null
@@ -1,17 +0,0 @@
-This is a generated file for the LaTeX (2e + expl3) validation system.
-Don't change this file in any respect.
-============================================================
-CFG FILE IS LOADED
-============================================================
-============================================================
-TEST 1: \afterassignment 
-============================================================
-> hello.
-<argument> ...d}}\foo } \x ={hello} \showthe \foo 
-\show \y 
-l.19 }
-> \y=macro:
-->world.
-<argument> ... \x ={hello} \showthe \foo \show \y 
-l.19 }
-============================================================
diff --git a/l3build/testfiles-plain/support/regression-test.cfg b/l3build/testfiles-plain/support/regression-test.cfg
deleted file mode 100644
index 8e03971..0000000
--- a/l3build/testfiles-plain/support/regression-test.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-% just a test
-
-\def\ISCFGLOADED{\SEPARATOR\TYPE{CFG FILE IS LOADED}\SEPARATOR}
diff --git a/l3build/testfiles/00-test-1.luatex.tlg b/l3build/testfiles/00-test-1.luatex.tlg
deleted file mode 100644
index 71c4d21..0000000
--- a/l3build/testfiles/00-test-1.luatex.tlg
+++ /dev/null
@@ -1,14 +0,0 @@
-This is a generated file for the LaTeX (2e + expl3) validation system.
-Don't change this file in any respect.
-============================================================
-TEST 1: \afterassignment 
-============================================================
-> hello.
-<argument> ...ef \y {world}}\foo } \x ={hello} \showthe \foo 
-                                                  \show \y 
-l. ...}
-> \y=macro:
-->world.
-<argument> ...rld}}\foo } \x ={hello} \showthe \foo \show \y 
-l. ...}
-============================================================
diff --git a/l3build/testfiles/00-test-1.lvt b/l3build/testfiles/00-test-1.lvt
deleted file mode 100644
index 587db27..0000000
--- a/l3build/testfiles/00-test-1.lvt
+++ /dev/null
@@ -1,18 +0,0 @@
-\input regression-test.tex\relax
-
-\documentclass{minimal}
-
-\begin{document}
-
-\newtoks\foo % \outer
-
-\START
-
-\TEST{\afterassignment}{
-  \def\x{\afterassignment{\edef\y{world}}\foo}
-  \x={hello}
-  \showthe\foo
-  \show\y
-}
-
-\END
diff --git a/l3build/testfiles/00-test-1.tlg b/l3build/testfiles/00-test-1.tlg
deleted file mode 100644
index 1652c36..0000000
--- a/l3build/testfiles/00-test-1.tlg
+++ /dev/null
@@ -1,14 +0,0 @@
-This is a generated file for the LaTeX (2e + expl3) validation system.
-Don't change this file in any respect.
-============================================================
-TEST 1: \afterassignment 
-============================================================
-> hello.
-<argument> ...d}}\foo } \x ={hello} \showthe \foo 
-                                                  \show \y 
-l. ...}
-> \y=macro:
-->world.
-<argument> ... \x ={hello} \showthe \foo \show \y 
-l. ...}
-============================================================
diff --git a/l3build/testfiles/01-expect.dtx b/l3build/testfiles/01-expect.dtx
deleted file mode 100644
index 9b9fe8b..0000000
--- a/l3build/testfiles/01-expect.dtx
+++ /dev/null
@@ -1,15 +0,0 @@
-\input regression-test.tex\relax
-\START
-\TEST{counter-math}{
-%<*test>
-  \OMIT
-  \newcounter{numbers}
-  \setcounter{numbers}{2}
-  \addtocounter{numbers}{2}
-  \stepcounter{numbers}
-  \TIMO
-  \typeout{\arabic{numbers}}
-%</test>
-%<expect>  \typeout{5}
-}
-\END
diff --git a/l3build/testfiles/01-expect.ins b/l3build/testfiles/01-expect.ins
deleted file mode 100644
index fd58066..0000000
--- a/l3build/testfiles/01-expect.ins
+++ /dev/null
@@ -1,6 +0,0 @@
-\input docstrip.tex
-\generate{
-  \file{\jobname-1.lvt}{\from{\jobname.dtx}{test}}
-  \file{\jobname-1.lve}{\from{\jobname.dtx}{expect}}
-}
-\endbatchfile
diff --git a/l3build/testfiles/support/regression-test.cfg b/l3build/testfiles/support/regression-test.cfg
deleted file mode 100644
index 32f4c50..0000000
--- a/l3build/testfiles/support/regression-test.cfg
+++ /dev/null
@@ -1,85 +0,0 @@
-%%
-%% This is file `regression-test-l3.cfg',
-%% generated with the docstrip utility.
-%%
-%% The original source files were:
-%%
-%% l3build.dtx  (with options: `lthree')
-%%
-%% EXPERIMENTAL CODE
-%%
-%% Do not distribute this file without also distributing the
-%% source files specified above.
-%%
-%% Do not distribute a modified version of this file.
-%%
-%%
-%% File l3build.dtx (C) Copyright 2014 The LaTeX3 Project
-%%
-%% It may be distributed and/or modified under the conditions of the
-%% LaTeX Project Public License (LPPL), either version 1.3c of this
-%% license or (at your option) any later version.  The latest version
-%% of this license is in the file
-%%
-%%    http://www.latex-project.org/lppl.txt
-%%
-%% This file is part of the "l3build bundle" (The Work in LPPL)
-%% and all files in that bundle must be distributed together.
-%%
-%% The released version of this bundle is available from CTAN.
-%%
-%% -----------------------------------------------------------------------
-%%
-%% The development version of the bundle can be found at
-%%
-%%    http://www.latex-project.org/svnroot/experimental/trunk/
-%%
-%% for those people who are interested.
-%%
-%%%%%%%%%%%
-%% NOTE: %%
-%%%%%%%%%%%
-%%
-%%   Snapshots taken from the repository represent work in progress and may
-%%   not work or may contain conflicting material!  We therefore ask
-%%   people _not_ to put them into distributions, archives, etc. without
-%%   prior consultation with the LaTeX Project Team.
-%%
-%% -----------------------------------------------------------------------
-%%
-\ifx\RequirePackage\@undefined\else
-  \OMIT
-  \RequirePackage{etex}
-  \TIMO
-\fi
-\newcount\regression at test@loop at int
-\long\def\regression at test@alloc#1#2{%
-  \regression at test@loop at int=\numexpr#1\relax
-  \regression at test@loop#2%
-}
-\long\def\regression at test@loop#1{%
-  \ifnum 0<\regression at test@loop at int
-    #1\regression at test@dummy
-    \advance\regression at test@loop at int by -1\relax
-    \expandafter\regression at test@loop
-    \expandafter#1%
-  \fi
-}
-\ifx\RequirePackage\@undefined
-  \expandafter\def\expandafter\newcount\expandafter{\newcount}
-  \expandafter\def\expandafter\newbox\expandafter{\newbox}
-  \expandafter\def\expandafter\newdimen\expandafter{\newdimen}
-  \expandafter\def\expandafter\newmuskip\expandafter{\newmuskip}
-  \expandafter\def\expandafter\newskip\expandafter{\newskip}
-\fi
-\regression at test@alloc {30} \newcount
-\regression at test@alloc {30} \newbox
-\regression at test@alloc {30} \newdimen
-\regression at test@alloc {30} \newmuskip
-\regression at test@alloc {30} \newskip
-
-\def\ISCFGLOADED{\SEPARATOR\TYPE{CFG FILE IS LOADED}\SEPARATOR}
-
-%%
-%%
-%% End of file `regression-test-l3.cfg'.
diff --git a/l3experimental/build.lua b/l3experimental/build.lua
index e0e2285..f51138f 100644
--- a/l3experimental/build.lua
+++ b/l3experimental/build.lua
@@ -10,9 +10,9 @@ module = ""
 -- Location of main directory: use Unix-style path separators
 maindir = ".."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3experimental/l3str/build.lua b/l3experimental/l3str/build.lua
index 78beb53..7408f27 100644
--- a/l3experimental/l3str/build.lua
+++ b/l3experimental/l3str/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 installfiles = {"*.def", "*.sty"}
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3experimental/xcoffins/build.lua b/l3experimental/xcoffins/build.lua
index 9937733..3ac7765 100644
--- a/l3experimental/xcoffins/build.lua
+++ b/l3experimental/xcoffins/build.lua
@@ -12,12 +12,12 @@ module = "xcoffins"
 maindir = "../.."
 
 -- Non-standard settings
-checkdeps   = {maindir .. "/l3build", maindir .. "/l3packages/xparse"}
+checkdeps   = {maindir .. "/l3packages/xparse"}
 typesetdeps = {maindir .. "/l3packages/xparse"}
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3experimental/xgalley/build.lua b/l3experimental/xgalley/build.lua
index 69f327f..d0d2d33 100644
--- a/l3experimental/xgalley/build.lua
+++ b/l3experimental/xgalley/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 testfiledir  = "" -- No tests
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3kernel/build.lua b/l3kernel/build.lua
index 99ed35a..4debaa8 100644
--- a/l3kernel/build.lua
+++ b/l3kernel/build.lua
@@ -33,7 +33,6 @@ versionfiles     =
   {"*.dtx", "README.md", "l3styleguide.tex", "l3syntax-changes.tex"}
 
 -- No deps other than the test system
-checkdeps   = {maindir .. "/l3build"}
 typesetdeps = {maindir .. "/l3packages/xparse"}
 unpackdeps  = { }
 
@@ -146,9 +145,9 @@ function typeset(file)
   end
 end
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3packages/build.lua b/l3packages/build.lua
index fb644e2..8dc9fc6 100644
--- a/l3packages/build.lua
+++ b/l3packages/build.lua
@@ -10,9 +10,9 @@ module = ""
 -- Location of main directory: use Unix-style path separators
 maindir = ".."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3packages/l3keys2e/build.lua b/l3packages/l3keys2e/build.lua
index c3344de..3e606b1 100644
--- a/l3packages/l3keys2e/build.lua
+++ b/l3packages/l3keys2e/build.lua
@@ -14,9 +14,9 @@ maindir = "../.."
 demofiles    = {"l3keys2e-demo.tex"}
 testfiledir  = "" -- No tests
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3packages/xfp/build.lua b/l3packages/xfp/build.lua
index acec9d4..935aa01 100644
--- a/l3packages/xfp/build.lua
+++ b/l3packages/xfp/build.lua
@@ -11,11 +11,11 @@ module = "xfp"
 maindir = "../.."
 
 -- Need xparse
-checkdeps = {maindir .. "/l3build", maindir .. "/l3packages/xparse"}
+checkdeps = {maindir .. "/l3packages/xparse"}
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3packages/xfrac/build.lua b/l3packages/xfrac/build.lua
index a8abe41..ba88f2a 100644
--- a/l3packages/xfrac/build.lua
+++ b/l3packages/xfrac/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 testfiledir  = "" -- No tests
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3packages/xparse/build.lua b/l3packages/xparse/build.lua
index 9cbdfde..9ef72df 100644
--- a/l3packages/xparse/build.lua
+++ b/l3packages/xparse/build.lua
@@ -10,9 +10,9 @@ module = "xparse"
 -- Location of main directory: use Unix-style path separators
 maindir = "../.."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3packages/xtemplate/build.lua b/l3packages/xtemplate/build.lua
index 0874103..e9b0464 100644
--- a/l3packages/xtemplate/build.lua
+++ b/l3packages/xtemplate/build.lua
@@ -10,9 +10,9 @@ module = "xtemplate"
 -- Location of main directory: use Unix-style path separators
 maindir = "../.."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/build.lua b/l3trial/build.lua
index 44dc911..61b7ba7 100644
--- a/l3trial/build.lua
+++ b/l3trial/build.lua
@@ -10,9 +10,9 @@ module = ""
 -- Location of main directory: use Unix-style path separators
 maindir = ".."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3auxdata/build.lua b/l3trial/l3auxdata/build.lua
index b3138d2..774babe 100644
--- a/l3trial/l3auxdata/build.lua
+++ b/l3trial/l3auxdata/build.lua
@@ -10,15 +10,12 @@ module = "l3auxdata"
 -- Location of main directory: use Unix-style path separators
 maindir = "../.."
 
--- Non-standard settings
-checkdeps   = {maindir .. "/l3experimental/l3str", maindir .. "/l3build"}
-testfiledir = ""
+--- Non-standard settings
 typesetcmds = ""
-typesetdeps = {maindir .. "/l3experimental/l3str"}
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3benchmark/build.lua b/l3trial/l3benchmark/build.lua
index 2c293f4..fc56b5e 100644
--- a/l3trial/l3benchmark/build.lua
+++ b/l3trial/l3benchmark/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 checkengines = {"pdftex", "xetex", "ptex", "uptex"}
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3bigint/build.lua b/l3trial/l3bigint/build.lua
index 7ec4c95..eec3dcb 100644
--- a/l3trial/l3bigint/build.lua
+++ b/l3trial/l3bigint/build.lua
@@ -10,12 +10,9 @@ module = "l3bigint"
 -- Location of main directory: use Unix-style path separators
 maindir = "../.."
 
--- Non-standard settings
-checkdeps   = {maindir .. "/l3kernel", maindir .. "/l3build"}
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3check/build.lua b/l3trial/l3check/build.lua
index 2fa904e..f201ff4 100644
--- a/l3trial/l3check/build.lua
+++ b/l3trial/l3check/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 testfiledir = ""
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3fp-extras/build.lua b/l3trial/l3fp-extras/build.lua
index 83ec3cf..442c070 100644
--- a/l3trial/l3fp-extras/build.lua
+++ b/l3trial/l3fp-extras/build.lua
@@ -10,9 +10,9 @@ module = "l3fp-extras"
 -- Location of main directory: use Unix-style path separators
 maindir = "../.."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3hooks/build.lua b/l3trial/l3hooks/build.lua
index 85ab1cb..7db3361 100644
--- a/l3trial/l3hooks/build.lua
+++ b/l3trial/l3hooks/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 checksearch = true
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3htoks/build.lua b/l3trial/l3htoks/build.lua
index b167e32..6e0142f 100644
--- a/l3trial/l3htoks/build.lua
+++ b/l3trial/l3htoks/build.lua
@@ -15,9 +15,9 @@ checkengines = {"pdftex", "xetex", "luatex"}
 checkruns    = 2
 checksearch  = true
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3image/build.lua b/l3trial/l3image/build.lua
index c91ef2b..821b3fd 100644
--- a/l3trial/l3image/build.lua
+++ b/l3trial/l3image/build.lua
@@ -10,9 +10,9 @@ module = "l3image"
 -- Location of main directory: use Unix-style path separators
 maindir = "../.."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
+-- Load the common build code
 dofile(maindir .. "/build-config.lua")
-dofile(maindir .. "/l3build/l3build.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3kernel-extras/build.lua b/l3trial/l3kernel-extras/build.lua
index 9c7c460..cdeb571 100644
--- a/l3trial/l3kernel-extras/build.lua
+++ b/l3trial/l3kernel-extras/build.lua
@@ -10,13 +10,12 @@ module = "l3kernel-extras"
 -- Location of main directory: use Unix-style path separators
 maindir = "../.."
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
 
 -- Non-standard settings (have to be after build-config)
 checkengines = {"pdftex", "xetex", "luatex"}
 
-dofile (maindir .. "/l3build/l3build.lua")
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3ldb/build.lua b/l3trial/l3ldb/build.lua
index b5dcff1..155d9ee 100644
--- a/l3trial/l3ldb/build.lua
+++ b/l3trial/l3ldb/build.lua
@@ -13,7 +13,6 @@ maindir = "../.."
 -- Non-standard settings
 checkdeps   =
   {
-    maindir .. "/l3build",
     maindir .. "/l3kernel",
     maindir .. "/l3packages/xtemplate"
   }
@@ -23,12 +22,13 @@ checksuppfiles  =
     "fontenc.sty",
     "ot1enc.def",
     "regression-test.cfg",
+    "regression-test.tex",
     "size10.clo",
   }
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3str-format-new/build.lua b/l3trial/l3str-format-new/build.lua
index 7d47a45..9f01e3e 100644
--- a/l3trial/l3str-format-new/build.lua
+++ b/l3trial/l3str-format-new/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 checksearch = true
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3trace/build.lua b/l3trial/l3trace/build.lua
index d2a5cdd..fe95ce2 100644
--- a/l3trial/l3trace/build.lua
+++ b/l3trial/l3trace/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 testfiledir = ""
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/l3tree/build.lua b/l3trial/l3tree/build.lua
index 33d7eb6..4c7322a 100644
--- a/l3trial/l3tree/build.lua
+++ b/l3trial/l3tree/build.lua
@@ -13,9 +13,9 @@ maindir = "../.."
 -- Non-standard settings
 testfiledir = ""
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/xbox/build.lua b/l3trial/xbox/build.lua
index 5731347..5537bf8 100644
--- a/l3trial/xbox/build.lua
+++ b/l3trial/xbox/build.lua
@@ -14,9 +14,9 @@ maindir = "../.."
 checkdeps   = {maindir .. "/l3kernel", maindir .. "/l3packages/xparse"}
 typesetdeps = {maindir .. "/l3kernel", maindir .. "/l3packages/xparse"}
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))
diff --git a/l3trial/xfont/build.lua b/l3trial/xfont/build.lua
index 18354b6..c1eb137 100644
--- a/l3trial/xfont/build.lua
+++ b/l3trial/xfont/build.lua
@@ -20,9 +20,9 @@ typesetdeps = {maindir .. "/l3kernel", "../l3hooks"}
 
 checksearch = true
 
--- Load the common build code: this is the one place that a path needs to be
--- hard-coded
--- As the build system is 'self-contained' there is no module set up here: just
---load the file in a similar way to a TeX \input
-dofile (maindir .. "/build-config.lua")
-dofile (maindir .. "/l3build/l3build.lua")
+-- Load the common build code
+dofile(maindir .. "/build-config.lua")
+
+-- Find and run the build system
+kpse.set_program_name("kpsewhich")
+dofile(kpse.lookup("l3build.lua"))

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the latex3-commits mailing list