summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/l3build
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2014-06-28 22:01:09 +0000
committerKarl Berry <karl@freefriends.org>2014-06-28 22:01:09 +0000
commit65b048d524ef9464d4039093986e267b277dafd9 (patch)
tree9ca9621d629641ee1ece91dd7735a289bb223ec6 /Master/texmf-dist/tex/latex/l3build
parent546e6790c84dde88b3abdffd431ece4e0061e0e6 (diff)
l3build
git-svn-id: svn://tug.org/texlive/trunk@34469 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/l3build')
-rw-r--r--Master/texmf-dist/tex/latex/l3build/l3build.lua1025
-rw-r--r--Master/texmf-dist/tex/latex/l3build/regression-test.tex214
2 files changed, 1239 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/l3build/l3build.lua b/Master/texmf-dist/tex/latex/l3build/l3build.lua
new file mode 100644
index 00000000000..99f68bdbc77
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/l3build/l3build.lua
@@ -0,0 +1,1025 @@
+--[[
+
+ File l3build.lua (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.
+
+--]]
+
+-- Version information: should be identical to that in l3build.dtx
+release_date = "2014/06/15"
+release_ver = "5141"
+
+-- Ensure the module and bundle exist
+module = module or ""
+bundle = bundle or ""
+
+-- Directory structure for the build system
+-- Use Unix-style path separators
+maindir = maindir or "."
+
+-- Substructure for tests and support files
+testfiledir = testfiledir or "testfiles" -- Set to "" to cancel any tests
+testsupdir = testsupdir 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
+else
+ moduledir = tdsroot .. "/" .. bundle .. "/" .. module
+end
+
+-- File types for various operations
+-- Use Unix-style globs
+-- All of these may be set earlier, so a initialised conditionally
+binaryfiles = binaryfiles or {"*.pdf", "*.zip"}
+checkfiles = checkfiles or { } -- Extra files unpacked purely for tests
+checksuppfiles = checksuppfiles or { }
+cmdchkfiles = cmdchkfiles or { }
+demofiles = demofiles or { }
+cleanfiles = cleanfiles or {"*.pdf", "*.zip"}
+excludefiles = excludefiles or {"*~"} -- Any Emacs stuff
+installfiles = installfiles or {"*.sty"}
+sourcefiles = sourcefiles or {"*.dtx", "*.ins"} -- Files to copy for unpacking
+txtfiles = txtfiles or {"*.markdown"}
+typesetfiles = typesetfiles or {"*.dtx"}
+typesetsuppfiles = typesetsuppfiles or { }
+unpackfiles = unpackfiles or {"*.ins"} -- Files to actually unpack
+unpacksuppfiles = unpacksuppfiles or { }
+
+-- 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 = "zip"
+
+checkopts = checkopts or "-interaction=batchmode"
+cmdchkopts = cmdchkopts or "-interaction=batchmode"
+typesetopts = typesetopts or "-interaction=nonstopmode"
+unpackopts = unpackopts or ""
+zipopts = zipopts or "-v -r -X"
+
+-- Engines for testing
+chkengines = chkengines or {"pdftex", "xetex", "luatex"}
+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
+-- here
+if checksearch == nil then
+ checksearch = true
+end
+if typesetsearch == nil then
+ typesetsearch = true
+end
+if unpacksearch == nil then
+ unpacksearch = true
+end
+
+-- Other required settings
+checkruns = checkruns or 1
+scriptname = scriptname or "build.lua" -- Script used in each directory
+typesetcmds = typesetcmds or ""
+
+-- Extensions for various file types: used to abstract out stuff a bit
+logext = logext or ".log"
+lvtext = lvtext or ".lvt"
+tlgext = tlgext or ".tlg"
+
+-- 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)
+
+--]]
+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 string.match (char, "^%w$") and char or "%" .. char
+ end
+
+ -- Convert tokens.
+ while true do
+ i = i + 1
+ char = string.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 = string.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
+
+-- File operation support
+-- Much of this is OS-dependent as Lua offers a very limited range of file
+-- operations 'natively'.
+
+-- Detect the operating system in use
+-- See http://www.lua.org/manual/5.2/manual.html#pdf-package.config for details
+-- of the string used here to pick up the operating system (Windows or
+-- 'not-Windows'
+-- 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
+if string.sub (package.config, 1, 1) == "\\" then
+ os_concat = "&"
+ os_diffext = ".fc"
+ os_diffexe = "fc /n"
+ os_null = "nul"
+ os_pathsep = ";"
+ os_setenv = "set"
+ os_windows = true
+else
+ os_concat = ";"
+ os_diffext = ".diff"
+ os_diffexe = "diff -c"
+ os_null = "/dev/null"
+ os_pathsep = ":"
+ os_setenv = "export"
+ os_windows = false
+end
+
+-- File operations are aided by the LuaFileSystem module, which is available
+-- within texlua
+lfs = require ("lfs")
+
+-- For cleaning out a directory, which also ensures that it exists
+function cleandir (dir)
+ mkdir (dir)
+ rm (dir, "*")
+end
+
+-- Copy files 'quietly'
+function cp (glob, source, dest)
+ for _,i in ipairs (filelist (source, glob)) do
+ local source = source .. "/" .. i
+ if os_windows then
+ os.execute (
+ "copy /y " .. unix_to_win (source) .. " "
+ .. unix_to_win (dest) .. " > nul"
+ )
+ else
+ os.execute ("cp -f " .. source .. " " .. dest)
+ end
+ end
+end
+
+-- OS-dependent test for a directory
+function direxists (dir)
+ local errorlevel
+ if os_windows then
+ errorlevel =
+ os.execute ("if not exist \"" .. unix_to_win (dir) .. "\" exit 1")
+ else
+ errorlevel = os.execute ("[ -d " .. dir .. " ]")
+ end
+ if errorlevel ~= 0 then
+ return (false)
+ end
+ return (true)
+end
+
+function fileexists (file)
+ local f = io.open (file, "r")
+ if f ~= nil then
+ io.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
+-- Not actually OS-dependent but in the same area
+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 string.match (entry, pattern) then
+ table.insert (files, entry)
+ end
+ else
+ if entry ~= "." and entry ~= ".." then
+ table.insert (files, entry)
+ end
+ end
+ end
+ end
+ return files
+end
+
+function mkdir (dir)
+ if os_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)
+ os.execute ("if not exist " .. dir .. "\\nul " .. "mkdir " .. dir)
+ else
+ os.execute ("mkdir -p " .. dir)
+ end
+end
+
+-- Rename
+function ren (dir, source, dest)
+ local dir = dir .. "/"
+ if os_windows then
+ os.execute ("ren " .. unix_to_win (dir) .. source .. " " .. dest)
+ else
+ os.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
+end
+
+-- Remove a directory tree
+function rmdir (dir)
+ -- First, make sure it exists to avoid any errors
+ mkdir (dir)
+ if os_windows then
+ os.execute ("rmdir /s /q " .. unix_to_win (dir) )
+ else
+ os.execute ("rm -r " .. dir)
+ end
+end
+
+-- Run a command in a given directory
+function run (dir, cmd)
+ local errorlevel = os.execute ("cd " .. dir .. os_concat .. cmd)
+ return (errorlevel)
+end
+
+-- Deal with the fact that Windows and Unix use different path separators
+function unix_to_win (path)
+ local path = string.gsub (path, "/", "\\")
+ return path
+end
+
+--
+-- Auxiliary functions which are used by more than one main function
+--
+
+-- Do some subtarget for all modules in a bundle
+function allmodules (target)
+ local errorlevel = 0
+ for _,i in ipairs (modules) do
+ print (
+ "Running script " .. scriptname .. " with target \"" .. target .. "\" for module "
+ .. i
+ )
+ errorlevel = run (i, "texlua " .. scriptname .. " " .. target)
+ if errorlevel > 0 then
+ return (errorlevel)
+ end
+ end
+ return (errorlevel)
+end
+
+-- Set up the check system files: needed for checking one or more tests and
+-- for saving the test files
+function checkinit ()
+ cleandir (localdir)
+ cleandir (testdir)
+ cleandir (unpackdir)
+ 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 ()
+ for _,i in ipairs (installfiles) do
+ cp (i, unpackdir, testdir)
+ end
+ for _,i in ipairs (checkfiles) do
+ cp (i, unpackdir, testdir)
+ end
+ if direxists (testsupdir) then
+ for _,i in ipairs (filelist (testsupdir)) do
+ cp (i, testsupdir, testdir)
+ end
+ end
+ for _,i in ipairs (checksuppfiles) do
+ cp (i, supportdir, testdir)
+ end
+end
+
+-- Unpack files needed to support testing/typesetting/unpacking
+function depinstall (deps)
+ for _,i in ipairs (deps) do
+ print ("Installing dependency: " .. i)
+ run (i, "texlua " .. scriptname .. " localinstall")
+ cleandir (unpackdir)
+ end
+end
+
+-- Convert the raw log file into one for comparison/storage: keeps only
+-- the 'business' part from the tests and removes system-dependent stuff
+function formatlog (logfile, newfile)
+ local function killcheck (line, kill)
+ local killnext = false
+ local line = line
+ -- Skip lines containing file dates
+ if string.match (line, "[^<]%d%d%d%d/%d%d/%d%d") then
+ line = ""
+ 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!
+ string.match (
+ string.gsub (line, "^\\openin", "\\openout"), "^\\openout%d = "
+ )
+ then
+ line = ""
+ elseif
+ -- Various things that only LuaTeX adds to boxes: at least while
+ -- we don't have bidi tests these lines can be removed
+ string.match (line, "^%.*\\whatsit$") or
+ string.match (line, "^%.*\\localinterlinepenalty=0$") or
+ string.match (line, "^%.*\\localbrokenpenalty=0$") or
+ string.match (line, "^%.*\\localleftbox=null$") or
+ string.match (line, "^%.*\\localrightbox=null$") then
+ line = ""
+ -- Pick up LuaTeX's \discretionary line and remove it and the next
+ -- line
+ elseif
+ string.match (line, "%.+\\discretionary") then
+ line = ""
+ killnext = true
+ elseif kill then
+ line = ""
+ end
+ return line, killnext
+ end
+ -- Substitutions to remove some non-useful changes
+ local function normalize (line)
+ local line = line
+ -- Remove test file name from lines
+ line = string.gsub (line, string.match (logfile, ".*/(.*)%" .. logext .. "$"), "")
+ -- Zap ./ at begin of filename
+ line = string.gsub (line, "%(%.%/", "(")
+ -- XeTeX knows only the smaller set of dimension units
+ line = string.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 = string.gsub (line, "\\csname\\endcsname ", "\\csname\\endcsname")
+ -- Zap "on line <num>" and replace with "on line ..."
+ line = string.gsub (line, "on line %d*", "on line ...")
+ -- Remove spaces at the start of lines: deals with the fact that LuaTeX
+ -- uses a different number to the other engines
+ line = string.gsub (line, "^%s+", "")
+ -- LuaTeX can give slightly different glue setting to pdfTeX:
+ -- handle this by restricting to four decimal places
+ line = string.gsub (
+ line, "glue set (%d+.%d%d%d%d)%dfil", "glue set %1fil"
+ )
+ -- For the present, remove direction information on boxes
+ line = string.gsub (line, ", direction TLT", "")
+ -- LuaTeX displays low chars differently: tidy up to ^^ notation
+ for i = 1, 31, 1 do
+ line = string.gsub (line, string.char (i), "^^" .. string.char (64 + i))
+ end
+ -- Minor LuaTeX bug: it prints an extra "'" in one message: add enough
+ -- context to hopefully hit only the bug
+ line = string.gsub (
+ line, "I''m going to assume", "I'm going to assume"
+ )
+ return line
+ end
+ local newlog = ""
+ local prestart = true
+ local skipping = false
+ local killnext = false
+ for line in io.lines (logfile) do
+ if line == "START-TEST-LOG" then
+ prestart = false
+ elseif line == "END-TEST-LOG" then
+ break
+ elseif line == "OMIT" then
+ skipping = true
+ elseif line == "TIMO" then
+ skipping = false
+ elseif not prestart and not skipping then
+ line = normalize (line)
+ line, killnext = killcheck (line, killnext)
+ if not string.match (line, "^ *$") then
+ newlog = newlog .. line .. "\n"
+ end
+ end
+ end
+ local newfile = io.open (newfile, "w")
+ io.output (newfile)
+ io.write (newlog)
+ io.close (newfile)
+end
+
+-- Runs a single test: needs the name of the test rather than the .lvt file
+-- One 'test' here may apply to multiple engines
+function runcheck (name, engine, hide)
+ local chkengines = chkengines
+ if engine then
+ chkengines = {engine}
+ end
+ local errorlevel = 0
+ for _,i in ipairs (chkengines) do
+ runtest (name, i, hide)
+ local testname = name .. "." .. i
+ local difffile = testdir .. "/" .. testname .. os_diffext
+ local newfile = testdir .. "/" .. testname .. logext
+ -- Use engine-specific file if available
+ local tlgfile = testfiledir .. "/" .. name .. "." .. i .. tlgext
+ if not fileexists (tlgfile) then
+ tlgfile = testfiledir .. "/" .. name .. tlgext
+ end
+ if os_windows then
+ tlgfile = unix_to_win (tlgfile)
+ end
+ local errlevel = os.execute (
+ os_diffexe .. " " .. tlgfile .. " " .. newfile .. " > " .. difffile
+ )
+ if errlevel == 0 then
+ os.remove (difffile)
+ else
+ errorlevel = errlevel
+ end
+ 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)
+ cp (name .. lvtext, testfiledir, testdir)
+ local engine = engine or stdengine
+ -- Engine name doesn't include the "la" for LaTeX!
+ local cmd = string.gsub (engine, "tex$", "latex")
+ local logfile = testdir .. "/" .. name .. logext
+ local lvtfile = name .. lvtext
+ local newfile = testdir .. "/" .. name .. "." .. engine .. logext
+ for i = 1, checkruns, 1 do
+ run (
+ testdir,
+ os_setenv .. " TEXINPUTS=." .. (checksearch and os_pathsep or "")
+ .. os_concat ..
+ cmd .. " " .. checkopts .. " " .. lvtfile
+ .. (hide and (" > " .. os_null) or "")
+ )
+ end
+ formatlog (logfile, newfile)
+end
+
+-- Strip the extension from a file name
+function stripext (file)
+ local name = string.gsub (file, "%..*$", "")
+ return name
+end
+
+function testexists (test)
+ if fileexists (testfiledir .. "/" .. test .. lvtext) then
+ return true
+ else
+ return false
+ end
+end
+
+-- Standard versions of the main targets for building modules
+
+-- Simply print out how to use the build system
+help = help or function ()
+ print ""
+ if testfiledir ~= "" then
+ print " build check - run automated check system "
+ end
+ if module ~= "" and testfiledir ~= "" then
+ print " build checklvt <name> - check one test file <name> for all engines"
+ print " build checklvt <name> <engine> - check one test file <name> for <engine> "
+ end
+ print " build clean - clean out directory tree "
+ if next (cmdchkfiles) ~= nil then
+ print " build cmdcheck - check commands documented are defined "
+ end
+ if module == "" or bundle == "" then
+ print " build ctan - create CTAN-ready archive "
+ end
+ print " build doc - runs all documentation files "
+ print " build install - install files in local texmf tree "
+ if module ~= "" and testfiledir ~= "" then
+ print " build savetlg <name> - save test log for <name> for all engines "
+ print " build savetlg <name> <engine> - save test log for <name> for <engine> "
+ end
+ print " build unpack - extract packages "
+ print ""
+end
+
+function check ()
+ local errorlevel = 0
+ if testfiledir ~= "" and direxists (testfiledir) then
+ checkinit ()
+ print ("Running checks on")
+ for _,i in ipairs (filelist (testfiledir, "*" .. lvtext)) do
+ local name = stripext (i)
+ print (" " .. name)
+ local errlevel = runcheck (name, nil, true)
+ if errlevel ~= 0 then
+ errorlevel = 1
+ end
+ end
+ if errorlevel ~= 0 then
+ print ("\n Check failed with difference files")
+ for _,i in ipairs (filelist (testdir, "*" .. os_diffext)) do
+ print (" - " .. testdir .. "/" .. i)
+ end
+ print ("")
+ else
+ print ("\n All checks passed\n")
+ end
+ end
+ return (errorlevel)
+end
+
+function checklvt (name, engine)
+ local engine = engine or stdengine
+ if testexists (name) then
+ checkinit ()
+ print ("Running checks on " .. name)
+ runcheck (name, engine)
+ if fileexists (testdir .. "/" .. name .. "." .. engine .. os_diffext) then
+ print (" Check fails with diff file")
+ print (
+ " " .. testdir .. os_dirsep .. name .. "." .. engine .. os_diffext)
+ else
+ print (" Check passes")
+ end
+ else
+ print ("Test \"" .. name .. "\" not set up!")
+ end
+end
+
+-- Remove all generated files
+function clean ()
+ rmdir (distribdir)
+ mkdir (distribdir)
+ cleandir (localdir)
+ cleandir (testdir)
+ cleandir (typesetdir)
+ cleandir (unpackdir)
+ for _,i in ipairs (cleanfiles) do
+ rm (".", i)
+ end
+end
+
+function bundleclean ()
+ allmodules ("clean")
+ for _,i in ipairs (cleanfiles) do
+ rm (".", i)
+ end
+ rmdir (ctandir)
+ rmdir (tdsdir)
+end
+
+-- Check commands are defined
+function cmdcheck ()
+ cleandir (localdir)
+ cleandir (testdir)
+ depinstall (checkdeps)
+ local engine = string.gsub (stdengine, "tex$", "latex")
+ print ("Checking source files")
+ for _,i in ipairs (cmdchkfiles) do
+ for _,j in ipairs (filelist (".", i)) do
+ print (" " .. stripext (j))
+ os.execute (
+ os_setenv .. " TEXINPUTS=." .. os_pathsep .. localdir ..
+ (checksearch and os_pathsep or "") .. os_concat ..
+ engine .. " " .. cmdchkopts .. " -output-directory=" .. testdir ..
+ " \"\\PassOptionsToClass{check}{l3doc} \\input " .. j .. "\""
+ .. " > " .. os_null
+ )
+ for line in io.lines (testdir .. "/" .. stripext (j) .. ".cmds") do
+ if string.match (line, "^%!") then
+ print (" - " .. string.match (line, "^%! (.*)"))
+ end
+ end
+ end
+ end
+end
+
+function ctan (standalone)
+ 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 .. " " .. "." .. " -x"
+ .. binfiles .. " " .. exclude
+ )
+ -- Then add the binary ones
+ run (
+ dir,
+ zipexe .. " " .. zipopts .. " -g ".. zipname .. " " .. ". -i" ..
+ binfiles .. " -x" .. exclude
+ )
+ end
+ local errorlevel
+ if standalone then
+ clean ()
+ errorlevel = check ()
+ bundle = module
+ else
+ bundleclean ()
+ errorlevel = allmodules ("bundlecheck")
+ end
+ if errorlevel == 0 then
+ mkdir (ctandir .. "/" .. bundle)
+ mkdir (tdsdir)
+ if standalone then
+ errorlevel = bundlectan ()
+ else
+ errorlevel = allmodules ("bundlectan")
+ end
+ end
+ if errorlevel == 0 then
+ for _,i in ipairs (txtfiles) do
+ for _,j in ipairs (filelist (".", i)) do
+ local function installtxt (name, dir)
+ cp (name, ".", dir)
+ ren (dir, name, stripext (name))
+ end
+ installtxt (j, ctandir .. "/" .. bundle)
+ installtxt (j, tdsdir .. "/doc/" .. tdsroot .. "/" .. bundle)
+ end
+ end
+ dirzip (tdsdir, bundle .. ".tds")
+ cp (bundle .. ".tds.zip", tdsdir, ctandir)
+ dirzip (ctandir, bundle)
+ cp (bundle .. ".zip", ctandir, ".")
+ else
+ print ("\n====================")
+ print ("Zip creation failed!")
+ print ("====================\n")
+ end
+end
+
+function bundlectan ()
+ local function install (source, dest, files, ctan)
+ local installdir = tdsdir .. "/" .. dest .. "/" .. moduledir
+ mkdir (installdir)
+ for _,i in ipairs (files) do
+ if ctan then
+ cp (i, source, ctandir .. "/" .. bundle)
+ end
+ cp (i, source, installdir)
+ end
+ end
+ unpack ()
+ install (unpackdir, "tex", installfiles, false)
+ local errorlevel = doc ()
+ if errorlevel == 0 then
+ -- Convert input names for typesetting into names of PDF files
+ local pdffiles = { }
+ for _,i in ipairs (typesetfiles) do
+ table.insert (pdffiles, (string.gsub (i, "%.%w+$", ".pdf")))
+ end
+ install (".", "doc", pdffiles, true)
+ install (".", "doc", demofiles, true)
+ install (".", "source", typesetfiles, true)
+ install (".", "source", sourcefiles, true)
+ end
+ return (errorlevel)
+end
+
+-- Typeset all required documents
+-- This function has several sub-parts, but as most are not needed anywhere
+-- else everything is done locally within the main function
+function doc ()
+ local function typeset (file)
+ local name = stripext (file)
+ -- A couple of short functions to deal with the repeated steps in a
+ -- clear way
+ local function index (name)
+ run (
+ typesetdir ,
+ "makeindex -s gind.ist -o " .. name .. ".ind " .. name .. ".idx"
+ )
+ end
+ local function typeset (file)
+ local errorlevel =
+ os.execute (
+ os_setenv .. " TEXINPUTS=" .. typesetdir ..
+ os_pathsep .. localdir .. (typesetsearch and os_pathsep or "") ..
+ os_concat ..
+ typesetexe .. " " .. typesetopts ..
+ " -output-directory=" .. typesetdir ..
+ " \"" .. typesetcmds ..
+ "\\input " .. typesetdir .. "/" .. file .. "\""
+ )
+ return errorlevel
+ end
+ os.remove (name .. ".pdf")
+ print ("Typesetting " .. name)
+ local errorlevel = typeset (file)
+ if errorlevel ~= 0 then
+ print (" ! Compilation failed")
+ return (errorlevel)
+ else
+ for i = 1, 2 do -- Do twice
+ index (name)
+ typeset (file)
+ end
+ cp (name .. ".pdf", typesetdir, ".")
+ end
+ return (errorlevel)
+ end
+ -- Set up
+ cleandir (localdir)
+ mkdir (typesetdir)
+ for _,i in ipairs (sourcefiles) do
+ cp (i, ".", typesetdir)
+ end
+ for _,i in ipairs (typesetfiles) do
+ cp (i, ".", typesetdir)
+ end
+ for _,i in ipairs (typesetsuppfiles) do
+ cp (i, supportdir, localdir)
+ end
+ depinstall (typesetdeps)
+ -- Main loop for doc creation
+ for _,i in ipairs (typesetfiles) do
+ for _,j in ipairs (filelist (".", i)) do
+ local errorlevel = typeset (j)
+ if errorlevel ~= 0 then
+ return (errorlevel)
+ end
+ end
+ end
+ return 0
+end
+
+-- Unpack then install
+function localinstall ()
+ unpack ()
+ for _,i in ipairs (installfiles) do
+ cp (i, unpackdir, localdir)
+ end
+end
+
+-- Locally install files: only deals with those extracted, not docs etc.
+function install ()
+ unpack ()
+ kpse.set_program_name ("latex")
+ local texmfhome = kpse.var_value ("TEXMFHOME")
+ local installdir = texmfhome .. "/tex/" .. moduledir
+ cleandir (installdir)
+ for _,i in ipairs (installfiles) do
+ cp (i, unpackdir, installdir)
+ end
+end
+
+function savetlg (name, engine)
+ local tlgfile = name .. (engine and ("." .. engine) or "") .. tlgext
+ local newfile = name .. "." .. (engine or stdengine) .. logext
+ if fileexists (testfiledir .. "/" .. name .. lvtext) then
+ checkinit ()
+ print ("Creating and copying " .. tlgfile)
+ runtest (name, engine, false)
+ ren (testdir, newfile, tlgfile)
+ cp (tlgfile, testdir, testfiledir)
+ else
+ print (
+ "Test input \"" .. testfiledir .. "/" .. name .. lvtext ..
+ "\" not found"
+ )
+ end
+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 ()
+ depinstall (unpackdeps)
+ bundleunpack ()
+end
+
+-- Split off from the main unpack so it can be used on a bundle and not
+-- leave only one modules files
+function bundleunpack ()
+ mkdir (localdir)
+ mkdir (unpackdir)
+ for _,i in ipairs (sourcefiles) do
+ cp (i, ".", unpackdir)
+ end
+ for _,i in ipairs (unpacksuppfiles) do
+ cp (i, supportdir, localdir)
+ end
+ for _,i in ipairs (unpackfiles) do
+ for _,j in ipairs (filelist (unpackdir, i)) do
+ os.execute (
+ -- Notice that os.execute is used from 'here' as this ensures that
+ -- localdir points to the correct place: running 'inside'
+ -- unpackdir would avoid the need for setting -output-directory
+ -- but at the cost of needing to correct the relative position
+ -- of localdir w.r.t. unpackdir
+ os_setenv .. " TEXINPUTS=" .. unpackdir .. os_pathsep .. localdir ..
+ (unpacksearch and os_pathsep or "") .. os_concat ..
+ unpackexe .. " " .. unpackopts .. " -output-directory=" .. unpackdir
+ .. " " .. unpackdir .. "/" .. j
+ )
+ end
+ end
+end
+
+function version ()
+ print (
+ "\nl3build Release " .. string.gsub (release_date, "/", "-") ..
+ " (SVN r" .. release_ver .. ")\n"
+ )
+end
+
+--
+-- The overall main function
+--
+
+function stdmain (target, file, engine)
+ -- 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 = { }
+ 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
+ table.insert (modules, entry)
+ end
+ end
+ end
+ if target == "doc" then
+ allmodules ("doc")
+ elseif target == "check" then
+ local errorlevel = allmodules ("bundlecheck")
+ if errorlevel ~=0 then
+ print ("There were errors: checks halted!\n")
+ os.exit (errorlevel)
+ end
+ elseif target == "clean" then
+ bundleclean ()
+ elseif target == "cmdcheck" and next (cmdchkfiles) ~= nil then
+ allmodules ("cmdcheck")
+ elseif target == "ctan" then
+ ctan ()
+ elseif target == "install" then
+ allmodules ("install")
+ elseif target == "unpack" then
+ -- bundleunpack avoids cleaning out the dir, so do it once here
+ cleandir (unpackdir)
+ allmodules ("bundleunpack")
+ elseif target == "version" then
+ version ()
+ else
+ help ()
+ end
+ else
+ if target == "bundleunpack" then -- 'Hidden' as only needed 'higher up'
+ depinstall (unpackdeps)
+ bundleunpack ()
+ elseif target == "bundlecheck" then
+ local errorlevel = check ()
+ os.exit (errorlevel)
+ elseif target == "bundlectan" then
+ bundlectan ()
+ elseif target == "doc" then
+ doc ()
+ elseif target == "check" and testfiledir ~= "" then
+ check ()
+ elseif target == "checklvt" and testfiledir ~= "" then
+ if file then
+ checklvt (file, engine)
+ else
+ help ()
+ end
+ elseif target == "clean" then
+ clean ()
+ elseif target == "cmdcheck" and next (cmdchkfiles) ~= nil then
+ cmdcheck ()
+ elseif target == "ctan" and bundle == "" then -- Stand-alone module
+ ctan (true)
+ elseif target == "install" then
+ install ()
+ elseif target == "localinstall" then -- 'Hidden' target
+ localinstall ()
+ elseif target == "savetlg" and testfiledir ~= "" then
+ if file then
+ savetlg (file, engine)
+ else
+ help ()
+ end
+ elseif target == "unpack" then
+ unpack ()
+ elseif target == "version" then
+ version ()
+ else
+ help ()
+ end
+ end
+end
+
+-- Allow main function to be disabled 'higher up'
+main = main or stdmain
+
+-- Call the main function
+main (arg[1], arg[2], arg[3])
diff --git a/Master/texmf-dist/tex/latex/l3build/regression-test.tex b/Master/texmf-dist/tex/latex/l3build/regression-test.tex
new file mode 100644
index 00000000000..83c29d157bc
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/l3build/regression-test.tex
@@ -0,0 +1,214 @@
+%%
+%% This is file `regression-test.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% l3build.dtx (with options: `package')
+%%
+%% 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.
+%%
+%% -----------------------------------------------------------------------
+%%
+\expandafter\edef\csname\detokenize{reset@catcodes}\endcsname{%
+ \catcode`\noexpand\@=\the\catcode`\@\relax
+}
+\catcode`\@=11 %
+\scrollmode
+\errorcontextlines=-1 %
+\showboxbreadth=\maxdimen
+\showboxdepth=\maxdimen
+\newlinechar=`\^^J
+\long\def\LONGTYPEOUT#1{%
+ \begingroup
+ \long\def\TYPE##1{##1}%
+ \immediate\write17{#1}%
+ \endgroup
+}
+\let\TYPE\LONGTYPEOUT
+\def\STARTMESSAGE{This is a generated file for the l3build validation system.}
+\def\START{\LONGTYPEOUT{START-TEST-LOG^^J^^J%
+ \STARTMESSAGE%
+^^J^^JDon't change this file in any respect.%
+^^J^^J\CTable^^J}}
+\begingroup
+\catcode`\^^\=0
+\catcode`\^^A=\catcode`\%
+^^\catcode`^^\ =11
+^^\catcode`^^\%=11
+^^\catcode`^^\#=11
+^^\catcode`^^\~=11
+^^\endlinechar=`^^\^^J
+^^\catcode`^^\\=11^^A
+^^\gdef^^\CTable{
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+}^^A
+^^\endgroup{}%
+\ifx\@@end\@undefined
+ \let\@@@end\end
+\else
+ \let\@@@end\@@end
+\fi
+\def\END
+ {%
+ \ifnum\currentgrouplevel>0 %
+ \LONGTYPEOUT{Bad grouping: \the\currentgrouplevel!}%
+ \fi
+ \ifnum\currentiflevel>1 %
+ \LONGTYPEOUT{Bad conditionals: \the\numexpr\currentiflevel-1!}%
+ \fi
+ \LONGTYPEOUT{END-TEST-LOG}\@@@end
+ }
+\let\@@end\END
+\def\FORMAT#1{\LONGTYPEOUT{Format: #1}%
+ \def\@tempa{#1}\ifx\@tempa\@EJ\else
+ \OMIT\TYPE{WARNING: Declared format #1,^^JActual format \@EJ}\TIMO\fi}
+\edef\@EJ{\fmtname <\fmtversion>}
+\def\AUTHOR#1{\LONGTYPEOUT{Author: #1}}
+\def\OMIT{\LONGTYPEOUT{OMIT}}
+\def\TIMO{\LONGTYPEOUT{TIMO}}
+\def\CLASS{\@ifnextchar[\OPTCLASS\XCLASS}
+\def\OPTCLASS[#1]#2{%
+ \TYPE{Main Class: #2^^J\space\space\space\space Options: #1}}
+\def\XCLASS#1{%
+ \TYPE{Main Class: #1}}
+\def\PACKAGE{\@ifnextchar[\OPTPACKAGE\XPACKAGE}
+\def\OPTPACKAGE[#1]#2{%
+ \TYPE{Package: #2^^J\space\space\space\space Options: #1}}
+\def\XPACKAGE#1{%
+ \TYPE{Package: #1}}
+\ifx\@ifnextchar\@undefined
+\long\def\@ifnextchar#1#2#3{%
+ \let\reserved@d=#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch}
+\def\@ifnch{%
+ \ifx\@let@token\@sptoken
+ \let\reserved@c\@xifnch
+ \else
+ \ifx\@let@token\reserved@d
+ \let\reserved@c\reserved@a
+ \else
+ \let\reserved@c\reserved@b
+ \fi
+ \fi
+ \reserved@c}
+\def\:{\let\@sptoken= } \: % this makes \@sptoken a space token
+\def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@token\@ifnch}
+\fi
+\def\CHECKCOMMAND#1{%
+ \ifx#1\@undefined\LONGTYPEOUT{Undefined \string#1}\else
+ \ifx#1\relax\LONGTYPEOUT{Relaxed \space\space\string#1}\else
+ \LONGTYPEOUT{Defined \space\space\string#1}\fi\fi}
+\OMIT
+\ifx\InputIfFileExists\@undefined
+\newread\@inputcheck
+\long\def\InputIfFileExists#1#2#3{%
+ \openin\@inputcheck#1\relax
+ \ifeof\@inputcheck
+ \def\reserved@a{#3}%
+ \else
+ \def\reserved@a{#2\input #1\relax}%
+ \fi
+ \closein\@inputcheck
+ \reserved@a}
+\fi
+\InputIfFileExists{regression-test.cfg}
+ {\LONGTYPEOUT{^^J***^^Jregression-test.cfg in operation^^J***^^J}}{}
+\TIMO
+\newcount \gTESTint
+\def\SEPARATOR{%
+ \TYPE{%
+ ============================================================%
+ }%
+}
+\long\def\TEST#1#2{%
+ \advance \gTESTint 1 %
+ \SEPARATOR
+ \LONGTYPEOUT{%
+ TEST \the\gTESTint: \detokenize{#1}}%
+ \SEPARATOR
+ \begingroup
+ \let\TYPE\LONGTYPEOUT
+ #2%
+ \endgroup
+ \SEPARATOR \LONGTYPEOUT{}%
+}
+\long\def\TESTEXP#1#2{%
+ \advance \gTESTint 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}}
+\reset@catcodes
+
+%%
+%%
+%% End of file `regression-test.tex'.