texlive[56424] Master/texmf-dist: l3 (24sep20)

commits+karl at tug.org commits+karl at tug.org
Thu Sep 24 22:46:15 CEST 2020


Revision: 56424
          http://tug.org/svn/texlive?view=revision&revision=56424
Author:   karl
Date:     2020-09-24 22:46:14 +0200 (Thu, 24 Sep 2020)
Log Message:
-----------
l3 (24sep20)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/l3backend/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex/l3backend/README.md
    trunk/Master/texmf-dist/doc/latex/l3experimental/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex/l3experimental/README.md
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3benchmark/l3benchmark.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3color/l3color.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3draw/l3draw-code.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3draw/l3draw.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3graphics/l3graphics.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3pdf/l3pdf-code.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3pdf/l3pdf.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-format.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/l3sys-shell/l3sys-shell.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf
    trunk/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex/l3kernel/README.md
    trunk/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
    trunk/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
    trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex
    trunk/Master/texmf-dist/source/latex/l3backend/l3backend-basics.dtx
    trunk/Master/texmf-dist/source/latex/l3backend/l3backend-box.dtx
    trunk/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx
    trunk/Master/texmf-dist/source/latex/l3backend/l3backend-draw.dtx
    trunk/Master/texmf-dist/source/latex/l3backend/l3backend-graphics.dtx
    trunk/Master/texmf-dist/source/latex/l3backend/l3backend-header.dtx
    trunk/Master/texmf-dist/source/latex/l3backend/l3backend-pdf.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3benchmark/l3benchmark.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-layers.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3graphics/l3graphics.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3pdf/l3pdf.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/l3sys-shell/l3sys-shell.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx
    trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins
    trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
    trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvipdfmx.def
    trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvips.def
    trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvisvgm.def
    trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-luatex.def
    trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
    trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-xetex.def
    trunk/Master/texmf-dist/tex/latex/l3experimental/l3benchmark/l3benchmark.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/l3color/l3color.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/l3draw/l3draw.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/l3graphics/l3graphics.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/l3pdf/l3pdf.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/l3sys-shell/l3sys-shell.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty
    trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua
    trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/l3backend/l3backend-code.pdf

Modified: trunk/Master/texmf-dist/doc/latex/l3backend/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3backend/CHANGELOG.md	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3backend/CHANGELOG.md	2020-09-24 20:46:14 UTC (rev 56424)
@@ -6,6 +6,11 @@
 
 ## [Unreleased]
 
+## [2020-09-24]
+
+### Fixed
+- Documented source as PDF
+
 ## [2020-09-11]
 
 ### Added
@@ -120,7 +125,8 @@
 - Include `l3backend` in file names
 - Moved backend code to internal for each 'parent' module
 
-[Unreleased]: https://github.com/latex3/latex3/compare/2020-09-11...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2020-09-24...HEAD
+[2020-09-24]: https://github.com/latex3/latex3/compare/2020-09-11...2020-09-24
 [2020-09-11]: https://github.com/latex3/latex3/compare/2020-09-01...2020-09-11
 [2020-09-01]: https://github.com/latex3/latex3/compare/2020-08-07...2020-09-01
 [2020-08-07]: https://github.com/latex3/latex3/compare/2020-06-29...2020-08-07

Modified: trunk/Master/texmf-dist/doc/latex/l3backend/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3backend/README.md	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3backend/README.md	2020-09-24 20:46:14 UTC (rev 56424)
@@ -1,7 +1,7 @@
 LaTeX3 Backend Drivers
 ======================
 
-Release 2020-09-11
+Release 2020-09-24
 
 This package forms parts of `expl3`, and contains the code used to interface
 with backends (drivers) across the `expl3` codebase. The functions here are

Added: trunk/Master/texmf-dist/doc/latex/l3backend/l3backend-code.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/l3backend/l3backend-code.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3backend/l3backend-code.pdf	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3backend/l3backend-code.pdf	2020-09-24 20:46:14 UTC (rev 56424)

Property changes on: trunk/Master/texmf-dist/doc/latex/l3backend/l3backend-code.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3experimental/CHANGELOG.md	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3experimental/CHANGELOG.md	2020-09-24 20:46:14 UTC (rev 56424)
@@ -7,6 +7,14 @@
 
 ## [Unreleased]
 
+### Changed
+- Use Lua pseudo-primitives instead of `\directlua`
+
+## [2020-09-24]
+
+### Added
+- Support for DeviceN color spaces
+
 ## [2020-09-11]
 
 ### Fixed
@@ -154,14 +162,14 @@
 
 ## [2018-05-12]
 
-### Changed 
-- Track changes in primitive naming in `l3kernel` 
+### Changed
+- Track changes in primitive naming in `l3kernel`
 
 ## [2018-04-30]
 
 ### Changed
-- Switch to ISO date format 
-- Improve cross-module use of internal functions 
+- Switch to ISO date format
+- Improve cross-module use of internal functions
 
 ## [2018-03-05]
 
@@ -174,7 +182,8 @@
 - New `l3color` module using `xcolor`-like expression syntax
 - New `l3draw` module, based on `pgf` layer of the TikZ system
 
-[Unreleased]: https://github.com/latex3/latex3/compare/2020-09-11...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2020-09-24...HEAD
+[2020-09-24]: https://github.com/latex3/latex3/compare/2020-09-11...2020-09-24
 [2020-09-11]: https://github.com/latex3/latex3/compare/2020-09-01...2020-09-11
 [2020-09-01]: https://github.com/latex3/latex3/compare/2020-08-07...2020-09-01
 [2020-08-07]: https://github.com/latex3/latex3/compare/2020-07-17...2020-08-07

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3experimental/README.md	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3experimental/README.md	2020-09-24 20:46:14 UTC (rev 56424)
@@ -1,7 +1,7 @@
 Experimental LaTeX3 Concepts
 ============================
 
-Release 2020-09-11
+Release 2020-09-24
 
 Overview
 --------

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3benchmark/l3benchmark.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3color/l3color.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3draw/l3draw-code.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3draw/l3draw.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3graphics/l3graphics.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3pdf/l3pdf-code.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3pdf/l3pdf.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3str/l3str-format.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/l3sys-shell/l3sys-shell.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/xcoffins/xcoffins.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/xgalley/l3galley.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3experimental/xgalley/xgalley.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md	2020-09-24 20:46:14 UTC (rev 56424)
@@ -7,6 +7,12 @@
 
 ## [Unreleased]
 
+## [2020-09-24]
+
+### Changed
+- Use Lua pseudo-primitives instead of `\directlua`
+- `\token_if_primitive:N(TF)` now reports pseudo-primitives as primitives in LuaTeX
+
 ## [2020-09-06]
 
 ### Fixed
@@ -765,7 +771,8 @@
 - Step func­tions have been added for dim vari­ables,
   e.g. `\dim_step_in­line:nnnn`
 
-[Unreleased]: https://github.com/latex3/latex3/compare/2020-09-06...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2020-09-24...HEAD
+[2020-09-24]: https://github.com/latex3/latex3/compare/2020-09-06...2020-09-24
 [2020-09-06]: https://github.com/latex3/latex3/compare/2020-09-03...2020-09-06
 [2020-09-03]: https://github.com/latex3/latex3/compare/2020-09-01...2020-09-03
 [2020-09-01]: https://github.com/latex3/latex3/compare/2020-08-07...2020-09-01

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/README.md	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/README.md	2020-09-24 20:46:14 UTC (rev 56424)
@@ -1,7 +1,7 @@
 LaTeX3 Programming Conventions
 ==============================
 
-Release 2020-09-06
+Release 2020-09-24
 
 Overview
 --------
@@ -33,7 +33,7 @@
 PDF generation is used). The bundle only works with the following engines:
 * pdfTeX v1.40 or later
 * XeTeX v0.99992 or later
-* LuaTeX v0.76 or later
+* LuaTeX v1.10 or later
 * e-(u)pTeX from mid-2012 onward
 
 pdfTeX v1.40 was released in 2007, and so any recent TeX distribution

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex	2020-09-24 20:46:14 UTC (rev 56424)
@@ -54,7 +54,7 @@
          {latex-team at latex-project.org}%
    }%
 }
-\date{Released 2020-09-06}
+\date{Released 2020-09-24}
 
 \pagenumbering{roman}
 \maketitle

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex	2020-09-24 20:46:14 UTC (rev 56424)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2020-09-06}
+\date{Released 2020-09-24}
 
 \begin{document}
 

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex	2020-09-24 20:46:14 UTC (rev 56424)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2020-09-06}
+\date{Released 2020-09-24}
 
 \newcommand{\TF}{\textit{(TF)}}
 

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex	2020-09-24 20:46:14 UTC (rev 56424)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2020-09-06}
+\date{Released 2020-09-24}
 
 \newcommand{\TF}{\textit{(TF)}}
 

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex	2020-09-24 20:46:14 UTC (rev 56424)
@@ -53,7 +53,7 @@
          {latex-team at latex-project.org}%
    }%
 }
-\date{Released 2020-09-06}
+\date{Released 2020-09-24}
 
 \pagenumbering{roman}
 \maketitle

Modified: trunk/Master/texmf-dist/source/latex/l3backend/l3backend-basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3backend/l3backend-basics.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3backend/l3backend-basics.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -70,27 +70,27 @@
 %    \begin{macrocode}
 \ProvidesExplFile
 %<*dvipdfmx>
-  {l3backend-dvipdfmx.def}{2020-09-11}{}
+  {l3backend-dvipdfmx.def}{2020-09-24}{}
   {L3 backend support: dvipdfmx}
 %</dvipdfmx>
 %<*dvips>
-  {l3backend-dvips.def}{2020-09-11}{}
+  {l3backend-dvips.def}{2020-09-24}{}
   {L3 backend support: dvips}
 %</dvips>
 %<*dvisvgm>
-  {l3backend-dvisvgm.def}{2020-09-11}{}
+  {l3backend-dvisvgm.def}{2020-09-24}{}
   {L3 backend support: dvisvgm}
 %</dvisvgm>
 %<*luatex>
-  {l3backend-luatex.def}{2020-09-11}{}
+  {l3backend-luatex.def}{2020-09-24}{}
   {L3 backend support: PDF output (LuaTeX)}
 %</luatex>
 %<*pdftex>
-  {l3backend-pdftex.def}{2020-09-11}{}
+  {l3backend-pdftex.def}{2020-09-24}{}
   {L3 backend support: PDF output (pdfTeX)}
 %</pdftex>
 %<*xetex>
-  {l3backend-xetex.def}{2020-09-11}{}
+  {l3backend-xetex.def}{2020-09-24}{}
   {L3 backend support: XeTeX}
 %</xetex>
 %    \end{macrocode}

Modified: trunk/Master/texmf-dist/source/latex/l3backend/l3backend-box.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3backend/l3backend-box.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3backend/l3backend-box.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3backend/l3backend-color.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -308,10 +308,11 @@
 %<*dvips>
 %    \end{macrocode}
 %
-% \begin{macro}{\@@_backend_select_separation:nn}
+% \begin{macro}{\@@_backend_select_separation:nn, \@@_backend_select_devicen:nn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_backend_select_separation:nn #1#2
   { \@@_backend_select:n { separation ~ #1 ~ #2 } }
+\cs_new_eq:NN \@@_backend_select_devicen:nn \@@_backend_select_separation:nn
 %    \end{macrocode}
 % \end{macro}
 %
@@ -362,7 +363,7 @@
       {
         !
         TeXDict ~ begin ~
-        /color \int_use:N \g_@@_separation_int
+        /color \int_use:N \g_@@_model_int
           {
             [ ~
               /Separation ~ ( \str_convert_pdfname:n {#1} ) ~
@@ -541,7 +542,31 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\@@_backend_devicen_init:nnn}
+%   Trivial as almost all of the work occurs in the shared code.
 %    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_devicen_init:nnn #1#2#3
+  {
+    \__kernel_backend_literal:e
+      {
+        !
+        TeXDict ~ begin ~
+        /color \int_use:N \g_@@_model_int
+          {
+            [ ~
+              /DeviceN ~
+              [ ~ #1 ~ ] ~
+              #2 ~
+              { ~ #3 ~ } ~
+            ] ~ setcolorspace
+          } ~ def ~
+        end
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
 %</dvips>
 %    \end{macrocode}
 %
@@ -549,10 +574,11 @@
 %<*dvisvgm>
 %    \end{macrocode}
 %
-% \begin{macro}{\@@_backend_select_separation:nn}
+% \begin{macro}{\@@_backend_select_separation:nn, \@@_backend_select_devicen:nn}
 %   No support at present.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_backend_select_separation:nn #1#2 { }
+\cs_new_protected:Npn \@@_backend_select_devicen:nn #1#2 { }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -573,7 +599,7 @@
 %<*dvipdfmx|luatex|pdftex|xetex>
 %    \end{macrocode}
 %
-% \begin{macro}{\@@_backend_select_separation:nn}
+% \begin{macro}{\@@_backend_select_separation:nn, \@@_backend_select_devicen:nn}
 % \begin{macro}{\@@_backend_select:n}
 %   Different syntaxes here as the stacks are accessed very differently.
 %    \begin{macrocode}
@@ -591,6 +617,7 @@
     \group_insert_after:N \@@_backend_reset:
   }
 %</dvipdfmx|xetex>
+\cs_new_eq:NN \@@_backend_select_devicen:nn \@@_backend_select_separation:nn
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
@@ -617,7 +644,7 @@
       }
     \@@_backend_separation_init:n
       {
-        /Separation
+        /Separation ~
         / \str_convert_pdfname:n {#1} ~ #2 ~
         \pdf_object_last:
       }
@@ -626,7 +653,7 @@
       {
         \pdfcoredict_gput:nnn
           { Page / Resources / ColorSpace }
-          { color \int_use:N \g_@@_separation_int }
+          { color \int_use:N \g_@@_model_int }
           { \pdf_object_last: }
       }
 %</luatex|pdftex>
@@ -638,7 +665,7 @@
 %<*dvipdfmx|xetex>
     \__kernel_backend_literal:x
       {
-        pdf:obj ~ @color \int_use:N \g_@@_separation_int \c_space_tl
+        pdf:obj ~ @color \int_use:N \g_@@_model_int \c_space_tl
           [#1]
       }
 %</dvipdfmx|xetex>
@@ -682,7 +709,68 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\@@_backend_devicen_init:nnn}
+% \begin{macro}[EXP]{\@@_backend_devicen_init:w}
+% \begin{macro}{\@@_backend_devicen_init:n}
+%   Similar to the Separations case, but with an arbitrary function for
+%   the alternative space work.
 %    \begin{macrocode}
+\cs_new_protected:Npn \@@_backend_devicen_init:nnn #1#2#3
+  {
+    \pdf_object_now:nx { stream }
+      {
+        {
+          /FunctionType ~ 4 ~
+          /Domain ~
+            [ ~
+              \prg_replicate:nn
+                { 0 \@@_backend_devicen_init:w #1 ~ \s_@@_stop }
+                { 0 ~ 1 ~ } ~
+            ] ~
+          /Range ~
+            [ ~
+              \str_case:nn {#2}
+                {
+                  { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                  { /DeviceGray } { 0 ~ 1 }
+                  { /DeviceRGB }  { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                } ~
+            ]
+        }
+        {#3}
+     }
+    \@@_backend_separation_init:n
+      {
+        /DeviceN ~
+        [ ~ #1 ~ ] ~
+        #2 ~
+        \pdf_object_last:
+      }
+%<*luatex|pdftex>
+    \use:x
+      {
+        \pdfcoredict_gput:nnn
+          { Page / Resources / ColorSpace }
+          { color \int_use:N \g_@@_model_int }
+          { \pdf_object_last: }
+      }
+%</luatex|pdftex>
+  }
+\cs_if_exist:NF \pdf_object_now:nn
+  { \cs_gset_protected:Npn \@@_backend_devicen_init:nnn #1#2#3 { } }
+\cs_new:Npn \@@_backend_devicen_init:w #1 ~ #2 \s_@@_stop
+  {
+    + 1
+    \tl_if_blank:nF {#2}
+      { \@@_backend_devicen_init:w #2 \s_@@_stop }
+  }
+\cs_new_eq:NN \@@_backend_devicen_init:n \@@_backend_separation_init:n
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%    \begin{macrocode}
 %</dvipdfmx|luatex|pdftex|xetex>
 %    \end{macrocode}
 %
@@ -730,7 +818,9 @@
 % \begin{macro}
 %   {
 %     \@@_backend_fill_separation:nn,
-%     \@@_backend_stroke_separation:nn
+%     \@@_backend_stroke_separation:nn,
+%     \@@_backend_fill_devicen:nn,
+%     \@@_backend_stroke_devicen:nn
 %   }
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2
@@ -737,6 +827,8 @@
   { \__kernel_backend_literal_pdf:n { /#1 ~ cs ~ #2 ~ scn } }
 \cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2
   { \__kernel_backend_literal_pdf:n { /#1 ~ CS ~ #2 ~ SCN } }
+\cs_new_eq:NN \@@_backend_fill_devicen:nn \@@_backend_fill_separation:nn
+\cs_new_eq:NN \@@_backend_stroke_devicen:nn \@@_backend_stroke_separation:nn
 %    \end{macrocode}
 % \end{macro}
 %
@@ -777,7 +869,9 @@
 % \begin{macro}
 %   {
 %     \@@_backend_fill_separation:nn,
-%     \@@_backend_stroke_separation:nn
+%     \@@_backend_stroke_separation:nn,
+%     \@@_backend_fill_devicen:nn,
+%     \@@_backend_stroke_devicen:nn
 %   }
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2
@@ -784,6 +878,8 @@
   { \__kernel_backend_postscript:n { /color.fc { #1 } def } }
 \cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2
   { \__kernel_backend_postscript:n { /color.sc { #1 } def } }
+\cs_new_eq:NN \@@_backend_fill_devicen:nn \@@_backend_fill_separation:nn
+\cs_new_eq:NN \@@_backend_stroke_devicen:nn \@@_backend_stroke_separation:nn
 %    \end{macrocode}
 % \end{macro}
 %
@@ -892,14 +988,16 @@
 % \begin{macro}
 %   {
 %     \@@_backend_fill_separation:nn,
-%     \@@_backend_stroke_separation:nn
+%     \@@_backend_stroke_separation:nn,
+%     \@@_backend_fill_devicen:nn,
+%     \@@_backend_stroke_devicen:nn
 %   }
 %   At present, these are no-ops.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2
-  { }
-\cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2
-  { }
+\cs_new_protected:Npn \@@_backend_fill_separation:nn #1#2 { }
+\cs_new_protected:Npn \@@_backend_stroke_separation:nn #1#2 { }
+\cs_new_eq:NN \@@_backend_fill_devicen:nn \@@_backend_fill_separation:nn
+\cs_new_eq:NN \@@_backend_stroke_devicen:nn \@@_backend_stroke_separation:nn
 %    \end{macrocode}
 % \end{macro}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3backend/l3backend-draw.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3backend/l3backend-draw.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3backend/l3backend-draw.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3backend/l3backend-graphics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3backend/l3backend-graphics.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3backend/l3backend-graphics.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3backend/l3backend-header.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3backend/l3backend-header.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3backend/l3backend-header.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3backend/l3backend-pdf.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3backend/l3backend-pdf.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3backend/l3backend-pdf.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3benchmark/l3benchmark.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3benchmark/l3benchmark.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3benchmark/l3benchmark.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -46,7 +46,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -129,7 +129,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3benchmark}{2020-09-11}{}
+\ProvidesExplPackage{l3benchmark}{2020-09-24}{}
   {L3 Experimental benchmarking}
 %    \end{macrocode}
 %
@@ -139,7 +139,7 @@
 %<@@=sys>
 %    \end{macrocode}
 %
-% \begin{macro}[EXP]{\sys_timer:}
+% \begin{macro}[EXP]{\sys_timer:, \@@_elapsedtime:, \@@_resettimer:}
 % \begin{macro}[EXP,pTF]{\sys_if_timer_exist:}
 %   In \LuaTeX{}, use emulation (see \pkg{l3luatex}),
 %   otherwise try to locate the primitive.  The
@@ -147,8 +147,27 @@
 %    \begin{macrocode}
 \sys_if_engine_luatex:TF
   {
+    \cs_new:Npn \@@_elapsedtime: { }
+    \cs_new:Npn \@@_resettimer: { }
+    \lua_now:n
+      {
+        local~gettimeofday = os.gettimeofday~
+        local~epoch = gettimeofday() - os.clock()~
+        local~write = tex.write~
+        local~tointeger = math.tointeger~
+        local~id = luatexbase.new_luafunction'@@_elapsedtime:'
+        lua.get_functions_table()[id] = function()
+        write(tointeger((gettimeofday() - epoch)*65536 // 1))
+        end~
+        token.set_lua('@@_elapsedtime:', id, 'global')
+        id = luatexbase.new_luafunction'@@_resettimer:'
+        lua.get_functions_table()[id] = function()
+          epoch = gettimeofday()
+        end~
+        token.set_lua('@@_resettimer:', id, 'global', 'protected')
+      }
     \cs_new:Npn \sys_timer:
-      { \lua_now:n { l3kernel.elapsedtime() } }
+      { \@@_elapsedtime: }
   }
   {
     \cs_if_exist:NT \tex_elapsedtime:D
@@ -163,8 +182,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}{\sys_gzero_timer:, \@@_timer_fp:}
-% \begin{variable}{\g_@@_timer_base_fp}
+% \begin{macro}{\sys_gzero_timer:}
 %   Three case, and in each case we define \cs{sys_gzero_timer:}.
 %    \begin{macrocode}
 \cs_if_exist:NTF \sys_timer:
@@ -172,7 +190,7 @@
     \sys_if_engine_luatex:TF
       {
         \cs_new_protected:Npn \sys_gzero_timer:
-          { \lua_now:n { l3kernel.resettimer() } }
+          { \@@_resettimer: }
       }
       { \cs_new_protected:Npn \sys_gzero_timer: { \tex_resettimer:D } }
   }
@@ -198,7 +216,6 @@
       }
   }
 %    \end{macrocode}
-% \end{variable}
 % \end{macro}
 %
 % \subsection{Benchmarking code}

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3color/l3color.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -46,7 +46,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -362,6 +362,7 @@
 %   Creates a new \meta{model} which is derived from the color model \meta{family}.
 %   The latter should be one of
 %   \begin{itemize}
+%     \item \texttt{DeviceN}
 %     \item \texttt{Separation}
 %   \end{itemize}
 %   (The \meta{family} may be given in mixed case as-in the PDF reference:
@@ -398,6 +399,13 @@
 % not the case, \pkg{l3color} will fallback to using black as the colorant in
 % any mixing.
 %
+% For a \texttt{DeviceN} space, there is one \emph{compulsory} key.
+% \begin{itemize}
+%   \item \texttt{names} The names of the components of the \texttt{DeviceN}
+%   space. Each should be either the \meta{name} of a \texttt{Separation} model,
+%   a process color name (\texttt{cyan}, etc.) or the special name \texttt{none}.
+% \end{itemize}
+%
 % \end{documentation}
 %
 % \begin{implementation}
@@ -413,7 +421,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3color}{2020-09-11}{}
+\ProvidesExplPackage{l3color}{2020-09-24}{}
   {L3 Experimental color support}
 %    \end{macrocode}
 %
@@ -439,8 +447,9 @@
 %
 % \subsection{Setup}
 %
-% \begin{variable}{\l_@@_internal_tl}
+% \begin{variable}{\l_@@_internal_int, \l_@@_internal_tl}
 %    \begin{macrocode}
+\int_new:N \l_@@_internal_int
 \tl_new:N \l_@@_internal_tl
 %    \end{macrocode}
 % \end{variable}
@@ -1517,14 +1526,40 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{variable}{\g_@@_separation_int}
-%   A tracker for the total number of separations.
+% \begin{variable}{\g_@@_model_int}
+%   A tracker for the total number of new models.
 %    \begin{macrocode}
-\int_new:N \g_@@_separation_int
+\int_new:N \g_@@_model_int
 %    \end{macrocode}
 % \end{variable}
 %
 % \begin{variable}
+%   {\c_@@_fallback_cmyk_tl, \c_@@_fallback_gray_tl, \c_@@_fallback_rgb_tl}
+%   Conversion from Separation or DeviceN spaces may not be possible; have
+%   a fallback to black.
+%    \begin{macrocode}
+\tl_const:Nn \c_@@_fallback_cmyk_tl { 0 ~ 0 ~ 0 ~ 1 }
+\tl_const:Nn \c_@@_fallback_gray_tl { 1 }
+\tl_const:Nn \c_@@_fallback_rgb_tl { 1 ~ 1 ~ 1 }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_colorants_prop}
+%   Mapping from names to colorants.
+%    \begin{macrocode}
+\prop_new:N \g_@@_colorants_prop
+\prop_gput:Nnn \g_@@_colorants_prop { black }   { Black }
+\prop_gput:Nnn \g_@@_colorants_prop { blue }    { Blue }
+\prop_gput:Nnn \g_@@_colorants_prop { cyan }    { Cyan }
+\prop_gput:Nnn \g_@@_colorants_prop { green }   { Green }
+\prop_gput:Nnn \g_@@_colorants_prop { magenta } { Magenta }
+\prop_gput:Nnn \g_@@_colorants_prop { none }    { None }
+\prop_gput:Nnn \g_@@_colorants_prop { red }     { Red }
+\prop_gput:Nnn \g_@@_colorants_prop { yellow }  { Yellow }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
 %   {
 %     \c_@@_model_whitepoint_CIELAB_a_tl   ,
 %     \c_@@_model_whitepoint_CIELAB_b_tl   ,
@@ -1553,6 +1588,31 @@
 %    \end{macrocode}
 % \end{variable}
 %
+% \begin{variable}{\g_@@_alternative_model_prop}
+%   For tracking the alternative model set up for separations, etc.
+%    \begin{macrocode}
+\prop_new:N \g_@@_alternative_model_prop
+\clist_map_inline:nn { cyan , magenta , yellow , black }
+  { \prop_gput:Nnn \g_@@_alternative_model_prop {#1} { cmyk } }
+\clist_map_inline:nn { red , green , blue }
+  { \prop_gput:Nnn \g_@@_alternative_model_prop {#1} { rgb } }
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_alternative_values_prop}
+%   Same for the values: a bit more involved.
+%    \begin{macrocode}
+\prop_new:N \g_@@_alternative_values_prop
+\prop_gput:Nnn \g_@@_alternative_values_prop { cyan }    {  1 , 0 , 0 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { magenta } {  0 , 1 , 0 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { yellow }  {  0 , 0 , 1 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { black }   {  0 , 0 , 0 , 1 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { red }   {  1 , 0 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { green } {  0 , 1 , 0 }
+\prop_gput:Nnn \g_@@_alternative_values_prop { blue }  {  0 , 0 , 1 }
+%    \end{macrocode}
+% \end{variable}
+%
 % \begin{macro}{\color_model_new:nnn, \@@_model_new:nnn}
 %   Set up a new model: in general this has to be handled by a family-dependent
 %   function. To avoid some \enquote{interesting} questions with casing, we
@@ -1665,7 +1725,7 @@
 \cs_new_protected:Npn \@@_model_separation:w
   #1 , #2 , #3 , #4 , #5 \s_@@_stop #6#7#8
   {
-    \int_gincr:N \g_@@_separation_int
+    \int_gincr:N \g_@@_model_int
     \tl_const:cn { c_@@_fallback_ #6 _tl } { 1 }
     \cs_new_eq:cN { @@_parse_mix_ #6 :nw } \@@_parse_mix_gray:nw
     \cs_new:cpn { @@_parse_model_ #6 :w } ##1 , ##2 \s_@@_stop
@@ -1675,11 +1735,14 @@
         \cs_new_protected:cpx { @@_backend_ ##1 _ #6 :n } ####1
           {
             \exp_not:c { @@_backend_ ##1 _ separation:nn }
-              { color \int_use:N \g_@@_separation_int } {####1}
+              { color \int_use:N \g_@@_model_int } {####1}
           }
       }
     \use:c { @@_model_separation_ #8 :nnnnnn }
       {#6} {#7} {#1} {#2} {#3} {#4}
+    \prop_gput:Nnn \g_@@_alternative_model_prop {#6} {#8}
+    \prop_gput:Nnx \g_@@_colorants_prop {#6}
+      { \str_convert_pdfname:n {#7} }
     \cs_new_protected:cpx { @@_model_ #6 _white: }
       {
         \prop_put:Nnn \exp_not:N \l_@@_named_white_prop {#6} { 0 }
@@ -1699,6 +1762,7 @@
       }
     \@@_model_convert:nnn {#1} { cmyk } { rgb }
     \@@_model_convert:nnn {#1} { cmyk } { gray }
+    \prop_gput:Nnn \g_@@_alternative_values_prop {#1} { #3 , #4 , #5 , #6 }
     \@@_backend_separation_init:nnnnn {#2} { /DeviceCMYK } { }
       { 0 ~ 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 ~ #6 }
   }
@@ -1712,6 +1776,7 @@
       }
     \@@_model_convert:nnn {#1} { rgb } { cmyk }
     \@@_model_convert:nnn {#1} { rgb } { gray }
+    \prop_gput:Nnn \g_@@_alternative_values_prop {#1} { #3 , #4 , #5 }
     \@@_backend_separation_init:nnnnn {#2} { /DeviceRGB } { }
       { 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 }
   }
@@ -1732,6 +1797,7 @@
         \fp_eval:n {##1 * #3} ~
         \fp_eval:n {##1 * #3}
       }
+    \prop_gput:Nnn \g_@@_alternative_values_prop {#1} {#3}
     \@@_backend_separation_init:nnnnn {#2} { /DeviceGray } { } { 0 } {#3}
   }
 %    \end{macrocode}
@@ -1797,6 +1863,529 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\@@_model_devicen:n}
+% \begin{macro}{\@@_model_devicen:nn}
+% \begin{macro}{\@@_model_devicen:nnn}
+% \begin{macro}{\@@_model_devicen:nnnn}
+% \begin{macro}
+%   {
+%     \@@_model_devicen_parse_1:nn ,
+%     \@@_model_devicen_parse_2:nn ,
+%     \@@_model_devicen_parse_3:nn ,
+%     \@@_model_devicen_parse_4:nn ,
+%     \@@_model_devicen_parse_generic:nn
+%  }
+%  \begin{macro}[EXP]{\@@_model_devicen_parse:nw}
+%  \begin{macro}[EXP]{\@@_model_devicen_mix:nw}
+% \begin{macro}{\@@_model_devicen_init:nnn}
+% \begin{macro}{\@@_model_devicen_init:nnnn}
+% \begin{macro}{\@@_model_devicen_tranform:w}
+% \begin{macro}
+%   {
+%     \@@_model_devicen_tranform_1:nnnnn ,
+%     \@@_model_devicen_tranform_3:nnnnn ,
+%     \@@_model_devicen_tranform_4:nnnnn ,
+%   }
+% \begin{macro}{\@@_model_devicen_tranform:nnn}
+% \begin{macro}[EXP]{\@@_model_devicen_colorant:n}
+% \begin{macro}{\@@_model_devicen_convert:nnn}
+% \begin{macro}
+%   {
+%     \@@_model_devicen_convert_cmyk:n ,
+%     \@@_model_devicen_convert_gray:n ,
+%     \@@_model_devicen_convert_rgb:n
+%   }
+% \begin{macro}{\@@_model_devicen_convert:nnnn}
+% \begin{macro}[EXP]{\@@_model_devicen_convert:n, \@@_model_devicen_convert_aux:n}
+% \begin{macro}[EXP]{\@@_model_devicen_convert:w}
+% \begin{macro}[EXP]{\@@_convert_devicen_cmyk:nnnnw}
+% \begin{macro}[EXP]{\@@_convert_devicen_cmyk:nnnnnnnnn}
+% \begin{macro}[EXP]{\@@_convert_devicen_cmyk_aux:nnnnw}
+% \begin{macro}[EXP]{\@@_convert_devicen_gray:nw}
+% \begin{macro}[EXP]{\@@_convert_devicen_gray:nnn}
+% \begin{macro}[EXP]{\@@_convert_devicen_gray_aux:nw}
+% \begin{macro}[EXP]{\@@_convert_devicen_rgb:nnnw}
+% \begin{macro}[EXP]{\@@_convert_devicen_rgb:nnnnnnn}
+% \begin{macro}[EXP]{\@@_convert_devicen_rgb_aux:nnnw}
+%   We require a list of component names here: one might call them colorants,
+%   but it's convenient to use \TeX{} names instead so we slightly adjust the
+%   terminology.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:n #1
+  {
+    \prop_get:NnNTF \l_@@_internal_prop { names }
+      \l_@@_internal_tl
+      {
+        \exp_args:NV \@@_model_devicen:nn
+          \l_@@_internal_tl {#1}
+      }
+      {
+        \__kernel_msg_error:nnn { color }
+          { DeviceN-requires-names } {#1}
+      }
+  }
+%    \end{macrocode}
+%   All valid models will have an alternative listed, either hard-coded for
+%   the core device ones, or dynamically added for Separations, etc.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:nn #1#2
+  {
+    \tl_clear:N \l_@@_model_tl
+    \clist_map_inline:nn {#1}
+      {
+        \prop_get:NnNTF \g_@@_alternative_model_prop {##1}
+          \l_@@_internal_tl
+          {
+            \tl_if_empty:NTF \l_@@_model_tl
+              { \tl_set_eq:NN \l_@@_model_tl \l_@@_internal_tl }
+              {
+                \str_if_eq:VVF \l_@@_model_tl \l_@@_internal_tl
+                  {
+                    \__kernel_msg_error:nnn { color }
+                      { DeviceN-inconsistent-alternative }
+                      {#2}
+                    \clist_map_break:n { \use_none:nnnn }
+                  }
+               }
+          }
+          {
+            \str_if_eq:nnF {##1} { none }
+              {
+                \__kernel_msg_error:nnn { color }
+                  { DeviceN-no-alternative }
+                  {#2}
+              }
+          }
+      }
+    \tl_if_empty:NTF \l_@@_model_tl
+      {
+        \__kernel_msg_error:nnn { color }
+          { DeviceN-no-alternative } {#2}
+      }
+      { \exp_args:NV \@@_model_devicen:nnn \l_@@_model_tl {#1} {#2} }
+  }
+%    \end{macrocode}
+%   We now complete the data we require by first finding out how many
+%   colorants there are, then moving on to begin constructing the function
+%   required to map to the alternative color space.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:nnn #1#2#3
+  {
+    \exp_args:Nx \@@_model_devicen:nnnn
+      { \clist_count:n {#2} } {#1} {#2} {#3}
+  }
+%    \end{macrocode}
+%   At this stage, we have checked everything is in place, so we can set up
+%   the \TeX{} and backend data structures. As for separations, it's not really
+%   possible in general to have a fallback, so we simply provide
+%   \enquote{black} for each element.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen:nnnn #1#2#3#4
+  {
+    \int_gincr:N \g_@@_model_int
+    \tl_const:cx { c_@@_fallback_ #4 _tl }
+      { \prg_replicate:nn {#1} { 1 ~ } }
+    \cs_if_exist_use:cF { @@_model_devicen_parse_ #1 :nn }
+      { \@@_model_devicen_parse_generic:nn }
+        {#4} {#1}
+    \clist_map_inline:nn { fill , stroke , select }
+      {
+        \cs_new_protected:cpx { @@_backend_ ##1 _ #4 :n } ####1
+          {
+            \exp_not:c { @@_backend_ ##1 _ devicen:nn }
+              { color \int_use:N \g_@@_model_int } {####1}
+          }
+      }
+    \cs_new_protected:cpx { @@_model_ #4 _white: }
+      {
+        \prop_put:Nnn \exp_not:N \l_@@_named_white_prop {#4}
+          { \prg_replicate:nn {#1} { 0 ~ } }
+        \exp_not:N \int_compare:nNnF { \tex_currentgrouplevel:D } = 0
+          { \group_insert_after:N \exp_not:c { @@_model_ #4 _ white: } }
+      }
+    \use:c { @@_model_ #4 _white: }
+    \@@_model_devicen_init:nnn {#1} {#2} {#3}
+    \@@_model_devicen_convert:nnn {#4} {#2} {#3}
+  }
+%    \end{macrocode}
+%   For short lists of DeviceN colors, wee can use hand-tuned parsing. This
+%   lines up with other models, where we allow for up to four components. For
+%   larger spaces,. rather than limit artificially, we use a somewhat slow
+%   approach based on open-ended commas-lists.
+%    \begin{macrocode}
+\cs_new_protected:cpn { @@_model_devicen_parse_1:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 \s_@@_stop
+      { {#1} { \@@_parse_number:n {##1} } }
+    \cs_new_eq:cN { @@_parse_mix_ #1 :nw  } \@@_parse_mix_gray:nw
+  }
+\cs_new_protected:cpn { @@_model_devicen_parse_2:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 , ##3 \s_@@_stop
+      { {#1} { \@@_parse_number:n {##1} ~ \@@_parse_number:n {##2} } }
+    \cs_new:cpn { @@_parse_mix_ #1 :nw }
+      ##1##2 ~ ##3 \s_@@_mark ##4 ~ ##5 \s_@@_stop
+      {
+        \fp_eval:n { ##2 * ##1 + ##4 * ( 1 - ##1 ) } \c_space_tl
+        \fp_eval:n { ##3 * ##1 + ##5 * ( 1 - ##1 ) }
+      }
+  }
+\cs_new_protected:cpn { @@_model_devicen_parse_3:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 , ##3 , ##4 \s_@@_stop
+      {
+        {#1}
+        {
+          \@@_parse_number:n {##1} ~
+          \@@_parse_number:n {##2} ~
+          \@@_parse_number:n {##3}
+        }
+      }
+    \cs_new_eq:cN { @@_parse_mix_ #1 :nw  } \@@_parse_mix_rgb:nw
+  }
+\cs_new_protected:cpn { @@_model_devicen_parse_4:nn } #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  }
+      ##1 , ##2 , ##3 , ##4 , ##5 \s_@@_stop
+      {
+        {#1}
+        {
+          \@@_parse_number:n {##1} ~
+          \@@_parse_number:n {##2} ~
+          \@@_parse_number:n {##3} ~
+          \@@_parse_number:n {##4}
+        }
+      }
+  \cs_new_eq:cN { @@_parse_mix_ #1 :nw } \@@_parse_mix_cmyk:nw
+  }
+\cs_new_protected:Npn \@@_model_devicen_parse_generic:nn #1#2
+  {
+    \cs_new:cpn { @@_parse_model_ #1 :w  } ##1 , ##2 \s_@@_stop
+      {
+        {#1}
+        { \@@_model_devicen_parse:nw {#2} ##1 , ##2 , \q_nil , \s_@@_stop }
+      }
+    \cs_new:cpx { @@_parse_mix_ #1 :nw }
+      ##1 ##2 \s_@@_mark ##3 \s_@@_stop
+      {
+        \exp_not:N \@@_model_devicen_mix:nw {##1}
+          ##2 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s_@@_mark
+          ##3 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_model_devicen_parse:nw #1#2 , #3 \s_@@_stop
+  {
+    \int_compare:nNnT {#1} > 0
+      {
+        \quark_if_nil:nTF {#2}
+          { \prg_replicate:nn {#1} { 0 ~ } }
+          {
+            \@@_parse_number:n {#2}
+            \int_compare:nNnT {#1} > 1 { ~ }
+            \exp_args:Nf \@@_model_devicen_parse:nw
+              { \int_eval:n { #1 - 1 } } #3 \s_@@_stop
+          }
+      }
+  }
+\cs_new:Npn \@@_model_devicen_mix:nw #1#2 ~ #3 \s_@@_mark #4 ~ #5 \s_@@_stop
+  {
+    \fp_eval:n { #2 * #1 + #4 * ( 1 - #1 ) }
+    \quark_if_nil:oF { \tl_head:w #3 \q_stop }
+      {
+        \c_space_tl
+        \@@_model_devicen_mix:nw {#1} #3 \s_@@_mark #5 \s_@@_stop
+      }
+  }
+%    \end{macrocode}
+%   To construct the tint transformation, we have to use PostScript. The
+%   aim is to have the final tint for each device colorant as
+%   \[
+%     1 - \prod_{n} (1 - X_{n} D_{X_{n}})
+%   \]
+%   where $X$ is a DeviceN colorant and $D$ is the amount of device colorant
+%   that the DeviceN colorant maps to. At the start of the process, the
+%   PostScript stack will contain the $X_{n}$ values, whilst we have the
+%   $D$ values on a per-DeviceN colorant basis. The more convenient approach
+%   for us is therefore to take each DeviceN colorant in turn and find the
+%   value $1 - X_{n} D_{X_{n}}$, multiplying as we go, and finalise with the
+%   subtraction. That contrasts to \pkg{colorspace}: it splits the process
+%   up by process color, which works better when you have a fixed list
+%   of colorants. (\pkg{colorspace} only supports up to $4$ DeviceN colors,
+%   and only \texttt{cmyk} as the alternative space.) To set this up,
+%   we first need to know the number of values in the target color space:
+%   this is easily handled as there are a very small range of possibles.
+%   Once we have that information, it's relatively easy to build the required
+%   PostScript using some generic code.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen_init:nnn #1#2#3
+  {
+    \exp_args:Ne \@@_model_devicen_init:nnnn
+      {
+        \str_case:nn {#2}
+          {
+            { cmyk } { 4 }
+            { gray } { 1 }
+            { rgb }  { 3 }
+          }
+      }
+      {#1} {#2} {#3}
+  }
+%    \end{macrocode}
+%   As we always need to split the alternative values into parts, we use a
+%   shared auxiliary and only use a minimal difference between code paths.
+%   Construction of the tint transformation is as far as possible done using
+%   loops, which means there are some inefficiencies for device colors in
+%   the \texttt{DeviceN} space: we roll the stack one-at-a-time even if there
+%   is a potential shortcut. However, that way there is nothing to special-case.
+%   Once this is sorted, we can write the tint transform object, which will
+%   remain as the last object until we sort out the final step: the colorant
+%   list.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen_init:nnnn #1#2#3#4
+  {
+    \tl_set:Nx \l_@@_internal_tl
+      { \prg_replicate:nn {#1} { 1.0 ~ }   }
+    \int_zero:N \l_@@_internal_int
+    \clist_map_inline:nn {#4}
+      {
+        \int_incr:N \l_@@_internal_int
+        \prop_get:NnN \g_@@_alternative_values_prop {##1}
+          \l_@@_value_tl
+        \exp_after:wN \@@_model_devicen_transform:w
+          \l_@@_value_tl , 0 , 0 , 0 \s_@@_stop {#1} {#2}
+      }
+    \tl_put_right:Nx \l_@@_internal_tl
+      {
+        \prg_replicate:nn {#1}
+          { neg ~ 1.0 ~ add ~ #1 ~ -1 ~ roll ~ }
+        \int_eval:n { #2 + 4 } ~ 4 ~ roll
+        \prg_replicate:nn {#2} { ~ pop }
+      }
+    \use:x
+      {
+        \@@_backend_devicen_init:nnn
+          {
+            \clist_map_function:nN {#4}
+              \@@_model_devicen_colorant:n
+          }
+          {
+            \str_case:nn {#3}
+              {
+                { cmyk } { /DeviceCMYK }
+                { gray } { /DeviceGray }
+                { rgb }  { /DeviceRGB }
+              }
+          }
+          { \exp_not:V \l_@@_internal_tl }
+      }
+  }
+\cs_new_protected:Npn \@@_model_devicen_transform:w
+  #1 , #2 , #3 , #4 , #5 \s_@@_stop #6#7
+  {
+    \use:c { @@_model_devicen_transform_ #6 :nnnnn }
+      {#1} {#2} {#3} {#4} {#7}
+  }
+\cs_new_protected:cpn { @@_model_devicen_transform_1:nnnnn } #1#2#3#4#5
+  { \@@_model_devicen_transform:nnn {#5} { 1 } {#1} }
+\cs_new_protected:cpn { @@_model_devicen_transform_3:nnnnn } #1#2#3#4#5
+  {
+    \clist_map_inline { #1 , #2 , #3 }
+      { \@@_model_devicen_transform:nnn {#5} { 3 } {##1} }
+  }
+\cs_new_protected:cpn { @@_model_devicen_transform_4:nnnnn } #1#2#3#4#5
+  {
+    \clist_map_inline:nn { #1 , #2 , #3 , #4 }
+      { \@@_model_devicen_transform:nnn {#5} { 4 } {##1} }
+  }
+\cs_new_protected:Npn \@@_model_devicen_transform:nnn #1#2#3
+  {
+    \tl_put_right:Nx \l_@@_internal_tl
+      {
+        \fp_compare:nNnF {#3} = \c_zero_fp
+          {
+            \int_eval:n { #1 - \l_@@_internal_int + #2 } ~ index ~
+              #3 ~ neg ~ mul ~ 1.0 ~ add ~ mul ~
+          }
+        #2 ~ -1 ~ roll ~
+      }
+  }
+\cs_new:Npn \@@_model_devicen_colorant:n #1
+  {
+    / \prop_item:Nn \g_@@_colorants_prop {#1} ~
+  }
+%    \end{macrocode}
+%   Here we need to set up conversion from the DeviceN space to the alternative
+%   at the \TeX{} level. This also means supplying methods for inter-converting
+%   to other parameter-based spaces. Essentially the approach is exactly the same
+%   as the PostScript, just expressed in \TeX{} terms.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_model_devicen_convert:nnn #1#2#3
+  {
+    \use:c { @@_model_devicen_convert_ #2 :nn } {#1} {#3}
+  }
+\cs_new_protected:Npn \@@_model_devicen_convert_cmyk:nn #1#2
+  {
+    \@@_model_convert:nnn {#1} { cmyk } { gray }
+    \@@_model_convert:nnn {#1} { cmyk } { rgb }
+    \@@_model_devicen_convert:nnnn {#1} { cmyk } { 4 } {#2}
+  }
+\cs_new_protected:Npn \@@_model_devicen_convert_gray:nn #1#2
+  {
+    \@@_model_convert:nnn {#1} { gray } { cmyk }
+    \@@_model_convert:nnn {#1} { gray } { rgb }
+    \@@_model_devicen_convert:nnnn {#1} { gray } { 1 } {#2}
+  }
+\cs_new_protected:Npn \@@_model_devicen_convert_rgb:nn #1#2
+  {
+    \@@_model_convert:nnn {#1} { rgb } { cmyk }
+    \@@_model_convert:nnn {#1} { rgb } { gray }
+    \@@_model_devicen_convert:nnnn {#1} { rgb } { 3 } {#2}
+  }
+\cs_new_protected:Npn \@@_model_devicen_convert:nnnn #1#2#3#4
+  {
+    \cs_new:cpx { @@_convert_ #1 _ #2 :w } ##1 \s_@@_stop
+      {
+        \exp_not:c { @@_convert_devicen_ #2 : \prg_replicate:nn {#3} { n } w }
+          \prg_replicate:nn {#3} { { 1 } }
+          ##1 \exp_not:N \s_@@_mark
+          \clist_map_function:nN {#4} \@@_model_devicen_convert:n
+          \exp_not:N \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_model_devicen_convert:n #1
+  {
+    { 
+      \exp_args:Ne \@@_model_devicen_convert_aux:n 
+        { \prop_item:Nn \g_@@_alternative_values_prop {#1} }
+    }
+  }
+\cs_new:Npn \@@_model_devicen_convert_aux:n #1
+  { \@@_model_devicen_convert_aux:w #1 , , , , \s_@@_stop }
+\cs_new:Npn \@@_model_devicen_convert_aux:w #1 , #2 , #3 , #4 , #5 \s_@@_stop
+  {
+    {#1}
+    \tl_if_blank:nF {#2}
+      {
+        {#2}
+        \tl_if_blank:nF {#3}
+          {
+            {#3}
+            \tl_if_blank:nF {#4} { {#4} }
+          }
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_cmyk:nnnnw
+  #1#2#3#4#5 ~ #6 \s_@@_mark #7#8 \s_@@_stop
+  {
+    \@@_convert_devicen_cmyk:nnnnnnnnn {#5} {#1} {#2} {#3} {#4} #7
+      #6 \s_@@_mark #8 \s_@@_stop
+  }
+\cs_new:Npn \@@_convert_devicen_cmyk:nnnnnnnnn #1#2#3#4#5#6#7#8#9
+  {
+    \use:e
+      {
+        \exp_not:N \@@_convert_devicen_cmyk_aux:nnnnw
+          { \fp_eval:n { #2 * (1 - (#1 * #6)) } }
+          { \fp_eval:n { #3 * (1 - (#1 * #7)) } }
+          { \fp_eval:n { #4 * (1 - (#1 * #8)) } }
+          { \fp_eval:n { #5 * (1 - (#1 * #9)) } }
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_cmyk_aux:nnnnw
+  #1#2#3#4 #5 \s_@@_mark #6 \s_@@_stop
+  {
+    \tl_if_blank:nTF {#5}
+      {
+        \fp_eval:n { 1 - #1 } ~
+        \fp_eval:n { 1 - #2 } ~
+        \fp_eval:n { 1 - #3 } ~
+        \fp_eval:n { 1 - #4 }
+      }
+      {
+        \@@_convert_devicen_cmyk:nnnnw {#1} {#2} {#3} {#4}
+          #5 \s_@@_mark #6 \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_gray:nw 
+  #1#2 ~ #3 \s_@@_mark #4#5 \s_@@_stop
+  {
+    \@@_convert_devicen_gray:nnn {#2} {#1} #4
+      #3 \s_@@_mark #5 \s_@@_stop
+  }
+\cs_new:Npn \@@_convert_devicen_gray:nnn #1#2#3
+  {
+    \exp_arsgs:Ne \@@_convert_devicen_gray_aux:nw
+      { \fp_eval:n { #2 * (1 - (#1 * #3)) } }
+  }
+\cs_new:Npn \@@_convert_devicen_gray_aux:nw
+  #1 #2 \s_@@_mark #3 \s_@@_stop
+  {
+    \tl_if_blank:nTF {#2}
+      { \fp_eval:n { 1 - #1 } }
+      {
+        \@@_convert_devicen_gray:nw {#1}
+          #2 \s_@@_mark #3 \s_@@_stop
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_rgb:nnnw
+  #1#2#3#4 ~ #5 \s_@@_mark #6#7 \s_@@_stop
+  {
+    \@@_convert_devicen_cmyk:nnnnnn {#4} {#1} {#2} {#3} #6
+      #5 \s_@@_mark #7 \s_@@_stop
+  }
+\cs_new:Npn \@@_convert_devicen_rgb:nnnnnnn #1#2#3#4#5#6#7
+  {
+    \use:e
+      {
+        \exp_not:N \@@_convert_devicen_rgb_aux:nnnw
+          { \fp_eval:n { #2 * (1 - (#1 * #5)) } }
+          { \fp_eval:n { #3 * (1 - (#1 * #6)) } }
+          { \fp_eval:n { #4 * (1 - (#1 * #7)) } }
+      }
+  }
+\cs_new:Npn \@@_convert_devicen_rgb_aux:nnnw
+  #1#2#3 #4 \s_@@_mark #5 \s_@@_stop
+  {
+    \tl_if_blank:nTF {#4}
+      {
+        \fp_eval:n { 1 - #1 } ~
+        \fp_eval:n { 1 - #2 } ~
+        \fp_eval:n { 1 - #3 }
+      }
+      {
+        \@@_convert_devicen_rgb:nnnw {#1} {#2} {#3}
+          #4 \s_@@_mark #5 \s_@@_stop
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
 % \subsection{Diagnostics}
 %
 % \begin{macro}{\color_show:n}
@@ -1830,7 +2419,7 @@
 %
 % \subsection{Messages}
 %
-% \begin{macrocode}
+%    \begin{macrocode}
 \__kernel_msg_new:nnnn { color } { CIELAB-requires-illuminant }
   { CIELAB~color~space~'#1'~require~an~illuminant. }
   {
@@ -1847,6 +2436,28 @@
     LaTeX~has~been~asked~to~convert~a~color~from~model~'#1'~
     to~model'#2',~but~there~is~no~method~available~to~do~that.
   }
+\__kernel_msg_new:nnnn { color } { DeviceN-inconsistent-alternative }
+  { DeviceN~color~spaces~require~a~single~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
+    but~the~constituent~colors~do~not~have~a~common~alternative~
+    color.
+  }
+\__kernel_msg_new:nnnn { color } { DeviceN-no-alternative }
+  { DeviceN~color~spaces~require~an~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
+    but~the~constituent~colors~do~not~all~have~a~device-based~alternative.
+  }
+\__kernel_msg_new:nnnn { color } { DeviceN-requires-names }
+  { DeviceN~color~space~'#1'~require~a~list~of~names. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space,~
+    but~no~\\ \\
+    \iow_indent:n { names~=~<names> }
+    \\ \\
+    key~was~given~with~the~correct~information.
+  }
 \__kernel_msg_new:nnnn { color } { model-already-defined }
   { Color~model~'#1'~already~defined. }
   {
@@ -1919,9 +2530,9 @@
     LaTeX~has~been~asked~to~create~a~new~color~model~called~'#1',~
     but~this~type~of~model~was~never~set~up.
   }
-% \end{macrocode}
+%    \end{macrocode}
 %
-% \begin{macrocode}
+%    \begin{macrocode}
 \__kernel_msg_new:nnn { color } { show }
   {
     The~color~#1~
@@ -1929,7 +2540,7 @@
       { is~undefined. }
       { has~the~properties: #2 }
   }
-% \end{macrocode}
+%    \end{macrocode}
 %
 %    \begin{macrocode}
 %</package>

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-boxes.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-layers.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-layers.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-layers.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-paths.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-points.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-scopes.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-softpath.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-state.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw-transforms.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3draw/l3draw.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -110,7 +110,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -1136,7 +1136,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3draw}{2020-09-11}{}
+\ProvidesExplPackage{l3draw}{2020-09-24}{}
   {L3 Experimental core drawing support}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3graphics/l3graphics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3graphics/l3graphics.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3graphics/l3graphics.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -46,7 +46,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -240,7 +240,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3graphics}{2020-09-11}{}
+\ProvidesExplPackage{l3graphics}{2020-09-24}{}
   {L3 Experimental graphics inclusion support}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3pdf/l3pdf.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3pdf/l3pdf.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3pdf/l3pdf.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -46,7 +46,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -190,7 +190,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3pdf}{2020-09-11}{}
+\ProvidesExplPackage{l3pdf}{2020-09-24}{}
   {L3 Experimental core PDF support}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3str/l3str-format.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -48,7 +48,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -166,7 +166,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3str-format}{2020-09-11}{}
+\ProvidesExplPackage{l3str-format}{2020-09-24}{}
   {L3 Experimental string formatting}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/l3sys-shell/l3sys-shell.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/l3sys-shell/l3sys-shell.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/l3sys-shell/l3sys-shell.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -46,7 +46,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -135,7 +135,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3sys-shell}{2020-09-11}{}
+\ProvidesExplPackage{l3sys-shell}{2020-09-24}{}
   {L3 Experimental system shell functions}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/xcoffins/xcoffins.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -56,7 +56,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -675,7 +675,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{xcoffins}{2020-09-11}{}
+\ProvidesExplPackage{xcoffins}{2020-09-24}{}
   {L3 Experimental design level coffins}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/l3galley.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -61,7 +61,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -686,7 +686,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3galley}{2020-09-11}{}
+\ProvidesExplPackage{l3galley}{2020-09-24}{}
   {L3 Experimental galley code}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3experimental/xgalley/xgalley.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -47,7 +47,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-11}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -734,7 +734,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{xgalley}{2020-09-11}{}
+\ProvidesExplPackage{xgalley}{2020-09-24}{}
   {L3 Experimental galley}
 \RequirePackage{xparse,xtemplate,l3galley}
 %    \end{macrocode}

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -24,7 +24,7 @@
 %
 %<*driver|generic|package|2ekernel>
 %</driver|generic|package|2ekernel>
-\def\ExplFileDate{2020-09-06}%
+\def\ExplFileDate{2020-09-24}%
 %<*driver>
 \documentclass[full]{l3doc}
 \usepackage{graphicx}
@@ -51,7 +51,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3.ins	2020-09-24 20:46:14 UTC (rev 56424)
@@ -60,7 +60,7 @@
       {
         \from{expl3.dtx}        {package}
         \from{l3bootstrap.dtx}  {package}
-        \from{l3names.dtx}      {package}
+        \from{l3names.dtx}      {package,tex}
         \from{l3basics.dtx}     {package}
         \from{l3expan.dtx}      {package}
         \from{l3quark.dtx}      {package}
@@ -70,9 +70,9 @@
         \from{l3int.dtx}        {package}
         \from{l3flag.dtx}       {package}
         \from{l3prg.dtx}        {package}
-        \from{l3sys.dtx}        {package}
+        \from{l3sys.dtx}        {package,tex}
         \from{l3clist.dtx}      {package}
-        \from{l3token.dtx}      {package}
+        \from{l3token.dtx}      {package,tex}
         \from{l3prop.dtx}       {package}
         \from{l3msg.dtx}        {package}
         \from{l3file.dtx}       {package}
@@ -165,6 +165,11 @@
 
 \endpreamble
 \nopostamble
-\generate{\file{expl3.lua}{\from{l3luatex.dtx}{package,lua}}}
+\generate{\file{expl3.lua}{
+  \from{l3luatex.dtx}{package,lua}
+  \from{l3names.dtx}{package,lua}
+  \from{l3sys.dtx}{package,lua}
+  \from{l3token.dtx}{package,lua}
+}}
 
 \endbatchfile

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -176,16 +176,23 @@
 \begingroup\expandafter\expandafter\expandafter\endgroup
 \expandafter\ifx\csname directlua\endcsname\relax
 \else
-  \ifnum\luatexversion<95 %
+  \ifnum\luatexversion<110 %
   \else
 %    \end{macrocode}
 %   For \LuaTeX{} we make sure the basic support is loaded:
 %   this is only necessary in plain.
+%
+%   Additionally we just ensure that \TeX{} has seen the csnames \cs{prg_return_true:}
+%   and \cs{prg_return_false:} before the Lua code builds these tokens.
 %    \begin{macrocode}
     \begingroup\expandafter\expandafter\expandafter\endgroup
     \expandafter\ifx\csname newcatcodetable\endcsname\relax
       \input{ltluatex}%
     \fi
+    \begingroup\edef\ignored{%
+      \expandafter\noexpand\csname prg_return_true:\endcsname
+      \expandafter\noexpand\csname prg_return_false:\endcsname
+    }\endgroup
     \directlua{require("expl3")}%
 %    \end{macrocode}
 %   As the user might be making a custom format, no assumption is made about
@@ -212,6 +219,9 @@
 % The code currently requires \eTeX{} and functionality equivalent to
 % \tn{pdfstrcmp}, and also driver and Unicode character support. This is
 % available in a reasonably-wide range of engines.
+%
+% For \LuaTeX, we require at least Lua 5.3 and the |token.set_lua| function.
+% This is available at least since \LuaTeX{} 1.10.
 %    \begin{macrocode}
 \begingroup
   \def\next{\endgroup}%
@@ -224,7 +234,7 @@
       These are available in the engines\LineBreak
       - pdfTeX v1.40\LineBreak
       - XeTeX v0.99992\LineBreak
-      - LuaTeX v0.95\LineBreak
+      - LuaTeX v1.10\LineBreak
       - e-(u)pTeX mid-2012\LineBreak
       or later.\LineBreak
       \LineBreak
@@ -247,7 +257,7 @@
     \fi
     \expandafter\ifx\csname directlua\endcsname\relax
     \else
-      \ifnum\luatexversion<76 \else 1\fi
+      \ifnum\luatexversion<110 \else 1\fi
     \fi
     =0 %
       \newlinechar`\^^J %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -79,7 +79,7 @@
 %
 % \title{The \cls{l3doc} class}
 % \author{\Team}
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 % \maketitle
 % \tableofcontents
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -63,7 +63,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -2636,18 +2636,9 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_size:n}
-%   A copy of the primitive where it's available, or the \LuaTeX{}
-%   equivalent if relevant.
+%   A copy of the primitive where it's available.
 %    \begin{macrocode}
 \cs_new_eq:NN \@@_size:n \tex_filesize:D
-\sys_if_engine_luatex:T
-  {
-    \cs_gset:Npn \@@_size:n #1
-      {
-        \lua_now:e
-          { l3kernel.filesize ( " \lua_escape:e {#1} " ) }
-      }
-  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -2753,9 +2744,7 @@
 %    \end{macrocode}
 %   Deal with the fact that the primitive might not be available.
 %    \begin{macrocode}
-\bool_lazy_or:nnF
-  { \cs_if_exist_p:N \tex_filesize:D }
-  { \sys_if_engine_luatex_p: }
+\cs_if_exist:NF \tex_filesize:D
   {
     \cs_gset:Npn \file_full_name:n #1
       {
@@ -2817,9 +2806,7 @@
 %   existence of the file with |.tex| extension in that directory, and
 %   if it exists we include the |.tex| extension in the result.
 %    \begin{macrocode}
-\bool_lazy_or:nnF
-  { \cs_if_exist_p:N \tex_filesize:D }
-  { \sys_if_engine_luatex_p: }
+\cs_if_exist:NF \tex_filesize:D
   {
     \prg_set_protected_conditional:Npnn \file_get_full_name:nN #1#2 { T , F , TF }
       {
@@ -2882,8 +2869,6 @@
 %   As the MD5 function has a slightly different syntax from the other commands,
 %   there is a little cleaning up to do.
 %    \begin{macrocode}
-\cs_new:Npn \file_mdfive_hash:n #1
-  { \@@_details:nn {#1} { mdfivesum } }
 \cs_new:Npn \file_size:n #1
   { \@@_details:nn {#1} { size } }
 \cs_new:Npn \file_timestamp:n #1
@@ -2898,20 +2883,10 @@
     \tl_if_blank:nF {#1}
       { \use:c { tex_file #2 :D } {#1} }
   }
-\sys_if_engine_luatex:TF
-  {
-    \cs_gset:Npn \@@_details_aux:nn #1#2
-      {
-        \lua_now:e
-          { l3kernel.file#2 ( " \lua_escape:e { #1 } " ) }
-      }
-  }
-  {
-    \cs_gset:Npn \file_mdfive_hash:n #1
-      { \exp_args:Ne \@@_mdfive_hash:n { \file_full_name:n {#1} } }
-    \cs_new:Npn \@@_mdfive_hash:n #1
-      { \tex_mdfivesum:D file {#1} }
-  }
+\cs_new:Npn \file_mdfive_hash:n #1
+  { \exp_args:Ne \@@_mdfive_hash:n { \file_full_name:n {#1} } }
+\cs_new:Npn \@@_mdfive_hash:n #1
+  { \tex_mdfivesum:D file {#1} }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
@@ -2973,34 +2948,21 @@
       length ~ \int_eval:n { #1 - #2 + 1 }
       {#3}
   }
-\sys_if_engine_luatex:T
+\cs_new:Npn \file_hex_dump:n #1
+  { \exp_args:Ne \@@_hex_dump:n { \file_full_name:n {#1} } }
+\sys_if_engine_luatex:TF
   {
-    \cs_gset:Npn \@@_hex_dump_auxiv:nnn #1#2#3
+    \cs_new:Npn \@@_hex_dump:n #1
       {
-        \lua_now:e
-          {
-            l3kernel.filedump
-              (
-                " \lua_escape:e {#3} " ,
-                \int_eval:n { #2 - 1 } ,
-                \int_eval:n { #1 - #2 + 1 }
-              )
-          }
+        \tl_if_blank:nF {#1}
+          { \tex_filedump:D whole {#1} {#1} }
       }
   }
-\cs_new:Npn \file_hex_dump:n #1
-  { \exp_args:Ne \@@_hex_dump:n { \file_full_name:n {#1} } }
-\cs_new:Npn \@@_hex_dump:n #1
   {
-    \tl_if_blank:nF {#1}
-      { \tex_filedump:D length \tex_filesize:D {#1} {#1} }
-  }
-\sys_if_engine_luatex:T
-  {
-    \cs_gset:Npn \@@_hex_dump:n #1
+    \cs_new:Npn \@@_hex_dump:n #1
       {
-        \lua_now:e
-          { l3kernel.filedump ( " \lua_escape:e { #1 } " ) }
+        \tl_if_blank:nF {#1}
+          { \tex_filedump:D length \tex_filesize:D {#1} {#1} }
       }
   }
 %    \end{macrocode}
@@ -3048,9 +3010,7 @@
 %   Where the primitive is not available, issue an error: this is a little
 %   more conservative than absolutely needed, but does work.
 %    \begin{macrocode}
-\bool_lazy_or:nnF
-  { \cs_if_exist_p:N \tex_filesize:D }
-  { \sys_if_engine_luatex_p: }
+\cs_if_exist:NF \tex_filesize:D
   {
     \cs_set_protected:Npn \@@_get_details:nnN #1#2#3
        {
@@ -3095,33 +3055,12 @@
 % \end{macro}
 %
 % \begin{macro}[EXP]{\@@_str_cmp:nn}
-% \begin{macro}[EXP]{\@@_str_escape:n}
 %   As we are doing a fixed-length \enquote{big} integer comparison, it
 %   is easiest to use the low-level behavior  of string comparisons.
 %    \begin{macrocode}
-\cs_new:Npn \@@_str_cmp:nn #1#2 { \tex_strcmp:D {#1} {#2} }
-\sys_if_engine_luatex:T
-  {
-    \cs_set:Npn \@@_str_cmp:nn #1#2
-      {
-        \lua_now:e
-          {
-            l3kernel.strcmp
-              (
-                " \@@_str_escape:n {#1}",
-                " \@@_str_escape:n {#2}"
-              )
-          }
-      }
-   \cs_new:Npn \@@_str_escape:n #1
-     {
-       \lua_escape:e
-         { \__kernel_tl_to_str:w \use:e { {#1} } }
-     }
-  }
+\cs_new_eq:NN \@@_str_cmp:nn \tex_strcmp:D
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
 %
 % \begin{macro}[EXP, pTF]{\file_compare_timestamp:nNn}
 % \begin{macro}[EXP]{\@@_compare_timestamp:nnN}
@@ -3169,15 +3108,7 @@
           }
       }
   }
-\sys_if_engine_luatex:TF
-  {
-    \cs_new:Npn \@@_timestamp:n #1
-      {
-        \lua_now:e
-          { l3kernel.filemoddate ( " \lua_escape:e {#1} " ) }
-      }
-  }
-  { \cs_new_eq:NN \@@_timestamp:n \tex_filemoddate:D }
+\cs_new_eq:NN \@@_timestamp:n \tex_filemoddate:D
 \cs_if_exist:NF \@@_timestamp:n
   {
     \prg_set_conditional:Npnn \file_compare_timestamp:nNn #1#2#3

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 % \maketitle
 %
 % \begin{documentation}

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -1239,27 +1239,9 @@
 % \subsection{Fast string comparison}
 %
 % \begin{macro}{\@@_str_if_eq:nn}
-%   A private version of the low-level string comparison function. As
-%   the nature of the arguments is restricted and as speed is of the essence,
-%   this version does not seek to deal with |#| tokens.
-%   No \pkg{l3sys} or \pkg{l3luatex} just yet so we have to define in terms of
-%   primitives.
+%   A private version of the low-level string comparison function.
 %    \begin{macrocode}
-\sys_if_engine_luatex:TF
-  {
-    \cs_new:Npn \@@_str_if_eq:nn #1#2
-      {
-        \tex_directlua:D
-          {
-            l3kernel.strcmp
-              (
-                " \tex_luaescapestring:D {#1}",
-                " \tex_luaescapestring:D {#2}"
-              )
-          }
-      }
-  }
-  { \cs_new_eq:NN \@@_str_if_eq:nn \tex_strcmp:D }
+\cs_new_eq:NN \@@_str_if_eq:nn \tex_strcmp:D
 %    \end{macrocode}
 % \end{macro}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 % \maketitle
 %
 % \begin{documentation}

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -49,7 +49,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -120,11 +120,17 @@
 % As well as interfaces for \TeX{}, there are a small number of Lua functions
 % provided here.
 %
-% \begin{function}{l3kernel}
-%   All public interfaces provided by the module are stored within the
-%   |l3kernel| table.
+% \begin{function}{ltx.utils}
+%   Most public interfaces provided by the module are stored within the
+%   |ltx.utils| table.
 % \end{function}
 %
+% \begin{function}[deprecated = 2021-12-31]{l3kernel}
+%   For compatibility reasons, there are also some deprecated interfaces provided
+%   in the |l3kernel| table. These do not return their result as Lua values but
+%   instead print them to \TeX.
+% \end{function}
+%
 % \begin{function}{l3kernel.charcat}
 %   \begin{syntax}
 %     |l3kernel.charcat(|\meta{charcode}, \meta{catcode}|)|
@@ -143,8 +149,9 @@
 %   for user input.
 % \end{function}
 %
-% \begin{function}{l3kernel.filedump}
+% \begin{function}{ltx.utils.filedump, l3kernel.filedump}
 %   \begin{syntax}
+%     \meta{dump}| = ltx.utils.filedump(|\meta{file}|,|\meta{offset}|,|\meta{length}|)| \\
 %     |l3kernel.filedump(|\meta{file}|,|\meta{offset}|,|\meta{length}|)|
 %   \end{syntax}
 %   Returns the uppercase hexadecimal representation of the content of the
@@ -154,8 +161,9 @@
 %   is read starting at the \meta{offset}.
 % \end{function}
 %
-% \begin{function}{l3kernel.filemdfivesum}
+% \begin{function}{ltx.utils.filemd5sum, l3kernel.filemdfivesum}
 %   \begin{syntax}
+%     \meta{hash}| = ltx.utils.filemd5sum(|\meta{file}|)| \\
 %     |l3kernel.filemdfivesum(|\meta{file}|)|
 %   \end{syntax}
 %   Returns the MD5 sum of the file contents read as bytes; note that
@@ -164,8 +172,9 @@
 %   nothing is returned with \emph{no error raised}.
 % \end{function}
 %
-% \begin{function}{l3kernel.filemoddate}
+% \begin{function}{ltx.utils.filemoddate, l3kernel.filemoddate}
 %   \begin{syntax}
+%     \meta{date}| = ltx.utils.filemoddate(|\meta{file}|)| \\
 %     |l3kernel.filemoddate(|\meta{file}|)|
 %   \end{syntax}
 %   Returns the date/time of last modification of the \meta{file} in the
@@ -179,8 +188,9 @@
 %   not found, nothing is returned with \emph{no error raised}.
 % \end{function}
 %
-% \begin{function}{l3kernel.filesize}
+% \begin{function}{ltx.utils.filesize, l3kernel.filesize}
 %   \begin{syntax}
+%     |size = ltx.utils.filesize(|\meta{file}|)| \\
 %     |l3kernel.filesize(|\meta{file}|)|
 %   \end{syntax}
 %   Returns the size of the \meta{file} in bytes. If the \meta{file} is not
@@ -313,11 +323,17 @@
 % \pkg{pdftexcmds} package.
 %
 % \begin{macro}{l3kernel}
+% \begin{macro}{ltx.utils}
 %   Create a table for the kernel's own use.
 %    \begin{macrocode}
 l3kernel = l3kernel or { }
+local l3kernel = l3kernel
+ltx = ltx or {utils={}}
+ltx.utils = ltx.utils or { }
+local ltxutils = ltx.utils
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 %   Local copies of global tables.
 %    \begin{macrocode}
@@ -331,7 +347,6 @@
 local tex      = tex
 local texio    = texio
 local tonumber = tonumber
-local unicode  = unicode
 %    \end{macrocode}
 %
 %   Local copies of standard functions.
@@ -342,23 +357,33 @@
 local format     = string.format
 local gsub       = string.gsub
 local lfs_attr   = lfs.attributes
-local md5_sum    = md5.sum
 local open       = io.open
-local os_clock   = os.clock
 local os_date    = os.date
-local os_exec    = os.execute
 local setcatcode = tex.setcatcode
 local sprint     = tex.sprint
 local cprint     = tex.cprint
 local write      = tex.write
 local write_nl   = texio.write_nl
+local utf8_char  = utf8.char
+
+local scan_int     = token.scan_int or token.scan_integer
+local scan_string  = token.scan_string
+local scan_keyword = token.scan_keyword
+local put_next     = token.put_next
+
+local true_tok     = token.create'prg_return_true:'
+local false_tok    = token.create'prg_return_false:'
 %    \end{macrocode}
 %
-%   Newer Con\TeX{}t releases replace the |unicode| library by |utf| and
-%   since Lua 5.3 we can even use the Lua standard |utf8| library.
 %    \begin{macrocode}
-local utf8_char = (utf8 and utf8.char) or (utf and utf.char) or unicode.utf8.char
-%    \end{macrocode}
+local function deprecated(table, name, func)
+  table[name] = function(...)
+    write_nl(format("Calling deprecated Lua function %s", name))
+    table[name] = func
+    return func(...)
+  end
+end
+%    \end{macrocode
 %
 %   Deal with Con\TeX{}t: doesn't use |kpse| library.
 %    \begin{macrocode}
@@ -371,8 +396,8 @@
 %   covered in \pkg{pdftexcmds} but is not currently required here.
 %    \begin{macrocode}
 local function escapehex(str)
-  write((gsub(str, ".",
-    function (ch) return format("%02X", byte(ch)) end)))
+  return (gsub(str, ".",
+    function (ch) return format("%02X", byte(ch)) end))
 end
 %    \end{macrocode}
 % \end{macro}
@@ -379,12 +404,12 @@
 %
 % \begin{macro}{l3kernel.charcat}
 %   Creating arbitrary chars using |tex.cprint|.
+%   The alternative approach using |token.put_next(token.create(...))|
+%   would be about 10\% slower.
 %    \begin{macrocode}
-local charcat
-function charcat(charcode, catcode)
+deprecated(l3kernel, 'charcat', function(charcode, catcode)
   cprint(catcode, utf8_char(charcode))
-end
-l3kernel.charcat = charcat
+end)
 %    \end{macrocode}
 % \end{macro}
 %
@@ -392,9 +417,10 @@
 %   Simple timing set up: give the result from the system clock in scaled
 %   seconds.
 %    \begin{macrocode}
-local base_time = 0
+local os_clock   = os.clock
+local base_clock_time = 0
 local function elapsedtime()
-  local val = (os_clock() - base_time) * 65536 + 0.5
+  local val = (os_clock() - base_clock_time) * 65536 + 0.5
   if val > 2147483647 then
     val = 2147483647
   end
@@ -402,12 +428,13 @@
 end
 l3kernel.elapsedtime = elapsedtime
 local function resettimer()
-  base_time = os_clock()
+  base_clock_time = os_clock()
 end
 l3kernel.resettimer = resettimer
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{ltx.utils.filedump}
 % \begin{macro}{l3kernel.filedump}
 %   Similar comments here to the next function: read the file in binary mode
 %   to avoid any line-end weirdness.
@@ -414,24 +441,43 @@
 %    \begin{macrocode}
 local function filedump(name,offset,length)
   local file = kpse_find(name,"tex",true)
-  if file then
-    local length = tonumber(length) or lfs_attr(file,"size")
-    local offset = tonumber(offset) or 0
-    local f = open(file,"rb")
-    if f then
-      if offset > 0 then
-        f:seek("set",offset)
-      end
-      local data = f:read(length)
-      escapehex(data)
-      f:close()
-    end
+  if not file then return end
+  local f = open(file,"rb")
+  if not f then return end
+  if offset and offset > 0 then
+    f:seek("set", offset)
   end
+  local data = f:read(length or 'a')
+  f:close()
+  return escapehex(data)
 end
-l3kernel.filedump = filedump
+ltxutils.filedump = filedump
+deprecated(l3kernel, "filedump", function(name, offset, length)
+  local dump = filedump(name, tonumber(offset), tonumber(length))
+  if dump then
+    write(dump)
+  end
+end)
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
+% \begin{macro}{md5.HEX}
+% Hash a string and return the hash in uppercase hexadecimal format.
+% In some engines, this is build-in. For traditional \LuaTeX{}, the conversion
+% to hexadecimal has to be done by us.
+%    \begin{macrocode}
+local md5_HEX = md5.HEX
+if not md5_HEX then
+  local md5_sum = md5.sum
+  function md5_HEX(data)
+    return escapehex(md5_sum(data))
+  end
+  md5.HEX = md5_HEX
+end
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}{ltx.utils.filemd5sum}
 % \begin{macro}{l3kernel.filemdfivesum}
 %   Read an entire file and hash it: the hash function itself is a built-in.
 %   As Lua is byte-based there is no work needed here in terms of UTF-8
@@ -439,94 +485,129 @@
 %   \LuaTeX{}). The file is read in binary mode so that no line ending
 %   normalisation occurs.
 %    \begin{macrocode}
-local function filemdfivesum(name)
-  local file =  kpse_find(name, "tex", true)
-  if file then
-    local f = open(file, "rb")
-    if f then
-      local data = f:read("*a")
-      escapehex(md5_sum(data))
-      f:close()
-    end
+local function filemd5sum(name)
+  local file = kpse_find(name, "tex", true) if not file then return end
+  local f = open(file, "rb") if not f then return end
+
+  local data = f:read("*a")
+  f:close()
+  return md5_HEX(data)
+end
+ltxutils.filemd5sum = filemd5sum
+deprecated(l3kernel, "filemdfivesum", function(name)
+  local hash = filemd5sum(name)
+  if hash then
+    write(hash)
   end
-end
-l3kernel.filemdfivesum = filemdfivesum
+end)
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
+% \begin{macro}{ltx.utils.filemoddate}
 % \begin{macro}{l3kernel.filemoddate}
+%   There are two cases: If the C standard library is C99 compliant,
+%   we can use |%z| to get the timezone in almost the right format.
+%   We only have to add primes and replace a zero or missing offset
+%   with |Z|.
+%
+%   Of course this would be boring, so Windows does things differently.
+%   There we have to manually calculate the offset.
 %   See procedure \texttt{makepdftime} in \texttt{utils.c} of
 %   \pdfTeX{}.
 %    \begin{macrocode}
-local function filemoddate(name)
-  local file =  kpse_find(name, "tex", true)
-  if file then
+local filemoddate
+if os_date'%z':match'^[+-]%d%d%d%d$' then
+  local pattern = lpeg.Cs(16 *
+      (lpeg.Cg(lpeg.S'+-' * '0000' * lpeg.Cc'Z')
+    + 3 * lpeg.Cc"'" * 2 * lpeg.Cc"'"
+    + lpeg.Cc'Z')
+  * -1)
+  function filemoddate(name)
+    local file = kpse_find(name, "tex", true)
+    if not file then return end
     local date = lfs_attr(file, "modification")
-    if date then
-      local d = os_date("*t", date)
-      if d.sec >= 60 then
-        d.sec = 59
+    if not date then return end
+    return pattern:match(os_date("D:%Y%m%d%H%M%S%z", date))
+  end
+else
+  local function filemoddate(name)
+    local file = kpse_find(name, "tex", true)
+    if not file then return end
+    local date = lfs_attr(file, "modification")
+    if not date then return end
+    local d = os_date("*t", date)
+    local u = os_date("!*t", date)
+    local off = 60 * (d.hour - u.hour) + d.min - u.min
+    if d.year ~= u.year then
+      if d.year > u.year then
+        off = off + 1440
+      else
+        off = off - 1440
       end
-      local u = os_date("!*t", date)
-      local off = 60 * (d.hour - u.hour) + d.min - u.min
-      if d.year ~= u.year then
-        if d.year > u.year then
-          off = off + 1440
-        else
-          off = off - 1440
-        end
-      elseif d.yday ~= u.yday then
-        if d.yday > u.yday then
-          off = off + 1440
-        else
-          off = off - 1440
-        end
+    elseif d.yday ~= u.yday then
+      if d.yday > u.yday then
+        off = off + 1440
+      else
+        off = off - 1440
       end
-      local timezone
-      if off == 0 then
-        timezone = "Z"
+    end
+    local timezone
+    if off == 0 then
+      timezone = "Z"
+    else
+      if off < 0 then
+        timezone = "-"
+        off = -off
       else
-        local hours = floor(off / 60)
-        local mins  = abs(off - hours * 60)
-        timezone = format("%+03d", hours)
-          .. "'" .. format("%02d", mins) .. "'"
+        timezone = "+"
       end
-      write("D:"
-        .. format("%04d", d.year)
-        .. format("%02d", d.month)
-        .. format("%02d", d.day)
-        .. format("%02d", d.hour)
-        .. format("%02d", d.min)
-        .. format("%02d", d.sec)
-        .. timezone)
+      timezone = format("%s%02d'%02d'", timezone, hours // 60, hours % 60)
     end
+    return format("D:%04d%02d%02d%02d%02d%02d%s",
+        d.year, d.month, d.day, d.hour, d.min, d.sec, timezone)
   end
 end
-l3kernel.filemoddate = filemoddate
+ltxutils.filemoddate = filemoddate
+deprecated(l3kernel, "filemoddate", function(name)
+  local hash = filemoddate(name)
+  if hash then
+    write(hash)
+  end
+end)
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
+% \begin{macro}{ltx.utils.filesize}
 % \begin{macro}{l3kernel.filesize}
 %   A simple disk lookup.
 %    \begin{macrocode}
 local function filesize(name)
-  local file =  kpse_find(name, "tex", true)
+  local file = kpse_find(name, "tex", true)
   if file then
     local size = lfs_attr(file, "size")
     if size then
-      write(size)
+      return size
     end
   end
 end
-l3kernel.filesize = filesize
+ltxutils.filesize = filesize
+deprecated(l3kernel, "filesize", function(name)
+  local size = filesize(name)
+  if size then
+    write(size)
+  end
+end)
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \begin{macro}{l3kernel.strcmp}
 %   String comparison which gives the same results as \pdfTeX{}'s
 %   \tn{pdfstrcmp}, although the ordering should likely not be relied upon!
 %    \begin{macrocode}
-local function strcmp(A, B)
+deprecated(l3kernel, "strcmp", function (A, B)
   if A == B then
     write("0")
   elseif A < B then
@@ -534,8 +615,7 @@
   else
     write("1")
   end
-end
-l3kernel.strcmp = strcmp
+end)
 %    \end{macrocode}
 % \end{macro}
 %
@@ -542,7 +622,8 @@
 % \begin{macro}{l3kernel.shellescape}
 %   Replicating the \pdfTeX{} log interaction for shell escape.
 %    \begin{macrocode}
-local function shellescape(cmd)
+local os_exec    = os.execute
+deprecated(l3kernel, "shellescape", function(cmd)
   local status,msg = os_exec(cmd)
   if status == nil then
     write_nl("log","runsystem(" .. cmd .. ")...(" .. msg .. ")\n")
@@ -551,8 +632,48 @@
   else
     write_nl("log","runsystem(" .. cmd .. ")...failed " .. (msg or "") .. "\n")
   end
+end)
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{luadef}
+% An internal function for defining control sequences form Lua which behave
+% like primitives. This acts as a wrapper around |token.set_lua| which accepts
+% a function instead of an index into the functions table.
+%    \begin{macrocode}
+local luacmd do
+  local token_create = token.create
+  local set_lua = token.set_lua
+  local undefined_cs = token.command_id'undefined_cs'
+
+  if not context and not luatexbase then require'ltluatex' end
+  if luatexbase then
+    local new_luafunction = luatexbase.new_luafunction
+    local functions = lua.get_functions_table()
+    function luacmd(name, func, ...)
+      local id
+      local tok = token_create(name)
+      if tok.command == undefined_cs then
+        id = new_luafunction(name)
+        set_lua(name, id, ...)
+      else
+        id = tok.index or tok.mode
+      end
+      functions[id] = func
+    end
+  elseif context then
+    local register = context.functions.register
+    local functions = context.functions.known
+    function luacmd(name, func, ...)
+      local tok = token.create(name)
+      if tok.command == undefined_cs then
+        token.set_lua(name, register(func), ...)
+      else
+        functions[tok.index or tok.mode] = func
+      end
+    end
+  end
 end
-l3kernel.shellescape = shellescape
 %    \end{macrocode}
 % \end{macro}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -55,18 +55,19 @@
 % performs the following tasks:
 % \begin{itemize}
 %   \item defines new names for all \TeX{} primitives;
+%   \item emulate required primitives not provided by default in \LuaTeX;
 %   \item switches to the category code r{\'e}gime for programming;
 % \end{itemize}
 %
-% This module is entirely dedicated to primitives, which should not be
-% used directly within \LaTeX3 code (outside of \enquote{kernel-level}
-% code). As such, the primitives are not documented here: \emph{The
-% \TeX{}book}, \emph{\TeX{} by Topic} and the manuals for \pdfTeX{},
-% \XeTeX{}, \LuaTeX{}, \pTeX{} and \upTeX{} should be consulted for
-% details of the primitives. These are named
-% \cs[no-index]{tex_\meta{name}:D}, typically based on the primitive's
-% \meta{name} in \pdfTeX{} and omitting a leading |pdf| when the
-% primitive is not related to pdf output.
+% This module is entirely dedicated to primitives (and emulations of
+% these), which should not be used directly within \LaTeX3 code
+% (outside of \enquote{kernel-level} code). As such, the primitives
+% are not documented here: \emph{The \TeX{}book}, \emph{\TeX{} by
+% Topic} and the manuals for \pdfTeX{}, \XeTeX{}, \LuaTeX{}, \pTeX{}
+% and \upTeX{} should be consulted for details of the primitives.
+% These are named \cs[no-index]{tex_\meta{name}:D}, typically based
+% on the primitive's \meta{name} in \pdfTeX{} and omitting a leading
+% |pdf| when the primitive is not related to pdf output.
 %
 % \end{documentation}
 %
@@ -75,7 +76,7 @@
 % \section{\pkg{l3names} implementation}
 %
 %    \begin{macrocode}
-%<*package>
+%<*package&tex>
 %    \end{macrocode}
 %
 % The prefix here is \texttt{kernel}.  A few places need |@@| to be left
@@ -111,7 +112,8 @@
 %
 % To allow extracting \enquote{just the names}, a bit of DocStrip fiddling.
 %    \begin{macrocode}
-%</package>
+%</package&tex>
+%<*names|tex>
 %<*names|package>
 %    \end{macrocode}
 %
@@ -609,9 +611,6 @@
   \@@_primitive:NN \pdfeachlinedepth      \tex_eachlinedepth:D
   \@@_primitive:NN \pdfeachlineheight     \tex_eachlineheight:D
   \@@_primitive:NN \pdfelapsedtime        \tex_elapsedtime:D
-  \@@_primitive:NN \pdffiledump           \tex_filedump:D
-  \@@_primitive:NN \pdffilemoddate        \tex_filemoddate:D
-  \@@_primitive:NN \pdffilesize           \tex_filesize:D
   \@@_primitive:NN \pdffirstlineheight    \tex_firstlineheight:D
   \@@_primitive:NN \pdffontexpand         \tex_fontexpand:D
   \@@_primitive:NN \pdffontsize           \tex_fontsize:D
@@ -622,7 +621,6 @@
   \@@_primitive:NN \pdflastypos           \tex_lastypos:D
   \@@_primitive:NN \pdfmapfile            \tex_mapfile:D
   \@@_primitive:NN \pdfmapline            \tex_mapline:D
-  \@@_primitive:NN \pdfmdfivesum          \tex_mdfivesum:D
   \@@_primitive:NN \pdfnoligatures        \tex_noligatures:D
   \@@_primitive:NN \pdfnormaldeviate      \tex_normaldeviate:D
   \@@_primitive:NN \pdfpageheight         \tex_pageheight:D
@@ -635,7 +633,6 @@
   \@@_primitive:NN \pdfrandomseed         \tex_randomseed:D
   \@@_primitive:NN \pdfresettimer         \tex_resettimer:D
   \@@_primitive:NN \pdfsavepos            \tex_savepos:D
-  \@@_primitive:NN \pdfstrcmp             \tex_strcmp:D
   \@@_primitive:NN \pdfsetrandomseed      \tex_setrandomseed:D
   \@@_primitive:NN \pdfshellescape        \tex_shellescape:D
   \@@_primitive:NN \pdftracingfonts       \tex_tracingfonts:D
@@ -681,6 +678,16 @@
 %</package>
 %<*names|package>
 %    \end{macrocode}
+% Some \pdfTeX{} primitives are handled here because they got dropped in
+% \LuaTeX{} but the corresponding internal names are emulated later. The
+% Lua code is already loaded at this point, so we shouldn't overwrite them.
+%    \begin{macrocode}
+  \@@_primitive:NN \pdfstrcmp             \tex_strcmp:D
+  \@@_primitive:NN \pdffilesize           \tex_filesize:D
+  \@@_primitive:NN \pdfmdfivesum          \tex_mdfivesum:D
+  \@@_primitive:NN \pdffilemoddate        \tex_filemoddate:D
+  \@@_primitive:NN \pdffiledump           \tex_filedump:D
+%    \end{macrocode}
 % \XeTeX{}-specific primitives. Note that \XeTeX{}'s \tn{strcmp} is
 % handled earlier and is \enquote{rolled up} into \tn{pdfstrcmp}.
 % A few cross-compatibility names which lack
@@ -1187,7 +1194,9 @@
 % End of the \enquote{just the names} part of the source.
 %    \begin{macrocode}
 %</names|package>
+%</names|tex>
 %<*package>
+%<*tex>
 %    \end{macrocode}
 %
 % The job is done: close the group (using the primitive renamed!).
@@ -1441,6 +1450,103 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
+%</tex>
+%    \end{macrocode}
+%
+% In \LuaTeX{}, we additionally emulate some primitives using Lua code.
+%    \begin{macrocode}
+%<*lua>
+%    \end{macrocode}
+%
+% \begin{macro}{\tex_strcmp:D}
+%   Compare two strings, expanding to |0| if they are equal,
+%   |-1| if the first one is smaller and |1| if the second one is smaller.
+%   Here \enquote{smaller} refers to codepoint order which does not correspond to
+%   the user expected order for most non-ASCII strings.
+%    \begin{macrocode}
+luacmd('tex_strcmp:D', function()
+  local first = scan_string()
+  local second = scan_string()
+  write(first == second and '0'
+     or first < second and '-1'
+     or '1')
+end, 'global')
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tex_Ucharcat:D}
+%   Creating arbitrary chars using |tex.cprint|.
+%   The alternative approach using |token.put_next(token.create(...))|
+%   would be about 10\% slower.
+%    \begin{macrocode}
+local cprint = tex.cprint
+luacmd('tex_Ucharcat:D', function()
+  local charcode = scan_int()
+  local catcode = scan_int()
+  cprint(catcode, utf8_char(charcode))
+end, 'global')
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tex_filesize:D}
+%   Wrap the function from |ltxutils|.
+%    \begin{macrocode}
+luacmd('tex_filesize:D', function()
+  local size = filesize(scan_string())
+  if size then write(size) end
+end, 'global')
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tex_mdfivesum:D}
+%   There are two cases: Either hash a file or a string.
+%   Both are already implemented in l3luatex or built-in.
+%    \begin{macrocode}
+luacmd('tex_mdfivesum:D', function()
+  local hash
+  if scan_keyword"file" then
+    hash = filemd5sum(scan_string())
+  else
+    hash = md5_HEX(scan_string())
+  end
+  if hash then write(hash) end
+end, 'global')
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tex_filemoddate:D}
+%   A primitive for getting the modification date of a file.
+%    \begin{macrocode}
+luacmd('tex_filemoddate:D', function()
+  local date = filemoddate(scan_string())
+  if date then write(date) end
+end, 'global')
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tex_filedump:D}
+%   An emulated primitive for getting a hexdump from a (partial) file.
+%   The length has a default of |0|. This is consistent with
+%   \pdfTeX, but it effectivly makes the primitive useless without an
+%   explicit |length|. Therefore we allow the keyword |whole| to be used
+%   instead of a length, indicating that the whole remaining file should
+%   be read.
+%    \begin{macrocode}
+luacmd('tex_filedump:D', function()
+  local offset = scan_keyword'offset' and scan_int() or nil
+  local length = scan_keyword'length' and scan_int()
+          or not scan_keyword'whole' and 0 or nil
+  local data = filedump(scan_string(), offset, length)
+  if data then write(data) end
+end, 'global')
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</lua>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
 %</package>
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -1121,44 +1121,12 @@
 % \end{macro}
 %
 % \begin{macro}[EXP]{\@@_if_eq:nn}
-% \begin{macro}[EXP]{\@@_escape:n}
-%   String comparisons rely on the primitive \cs[index=pdfstrcmp]{(pdf)strcmp} if available:
-%   \LuaTeX{} does not have it, so emulation is required. As the net result
-%   is that we do not \emph{always} use the primitive, the correct approach
-%   is to wrap up in a function with defined behaviour. That's done by
-%   providing a wrapper and then redefining in the \LuaTeX{} case. Note that
-%   the necessary Lua code is loaded in \pkg{l3boostrap}.
-%   The need to detokenize and force
-%   expansion of input arises from the case where a |#| token is used in the
-%   input, \emph{e.g.}~|\__str_if_eq:nn {#} { \tl_to_str:n {#} }|, which
-%   otherwise would fail as \cs{tex_luaescapestring:D} does not double
-%   such tokens.
+%   String comparisons rely on the primitive \cs[index=pdfstrcmp]{(pdf)strcmp},
+%   so we define a new name for it.
 %    \begin{macrocode}
-\cs_new:Npn \@@_if_eq:nn #1#2 { \tex_strcmp:D {#1} {#2} }
-\cs_if_exist:NT \tex_luatexversion:D
-   {
-     \cs_set_eq:NN \lua_escape:e \tex_luaescapestring:D
-     \cs_set_eq:NN \lua_now:e    \tex_directlua:D
-     \cs_set:Npn \@@_if_eq:nn #1#2
-       {
-          \lua_now:e
-            {
-              l3kernel.strcmp
-                (
-                  " \@@_escape:n {#1} " ,
-                  " \@@_escape:n {#2} "
-                )
-            }
-       }
-     \cs_new:Npn \@@_escape:n #1
-       {
-         \lua_escape:e
-           { \__kernel_tl_to_str:w \use:e { {#1} } }
-       }
-   }
+\cs_new_eq:NN \@@_if_eq:nn \tex_strcmp:D
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
 %
 % \begin{macro}[pTF, EXP]
 %   {

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -317,6 +317,7 @@
 %
 %    \begin{macrocode}
 %<*package>
+%<*tex>
 %    \end{macrocode}
 %
 % \subsubsection{Detecting the engine}
@@ -391,23 +392,26 @@
 %   however, is reliable only if the user doesn't change
 %   \cs{tex_pdfoutput:D} before loading this code.
 %    \begin{macrocode}
-\str_const:Nx \c_sys_engine_exec_str
-  {
-    \sys_if_engine_pdftex:T { pdf }
-    \sys_if_engine_xetex:T  { xe  }
-    \sys_if_engine_ptex:T   { ep  }
-    \sys_if_engine_uptex:T  { eup }
-    \sys_if_engine_luatex:T
-      {
-        lua \lua_now:e
-          {
-            if (pcall(require, 'luaharfbuzz')) then ~
-              tex.print("hb") ~
-            end
-          }
-      }
-    tex
-  }
+\group_begin:
+  \cs_set_eq:NN \lua_now:e    \tex_directlua:D
+  \str_const:Nx \c_sys_engine_exec_str
+    {
+      \sys_if_engine_pdftex:T { pdf }
+      \sys_if_engine_xetex:T  { xe  }
+      \sys_if_engine_ptex:T   { ep  }
+      \sys_if_engine_uptex:T  { eup }
+      \sys_if_engine_luatex:T
+        {
+          lua \lua_now:e
+            {
+              if (pcall(require, 'luaharfbuzz')) then ~
+                tex.print("hb") ~
+              end
+            }
+        }
+      tex
+    }
+\group_end:
 \str_const:Nx \c_sys_engine_format_str
   {
     \cs_if_exist:NTF \fmtname
@@ -647,15 +651,38 @@
 % \end{variable}
 %
 % \begin{macro}{\sys_shell_now:n}
+% \begin{macro}{\@@_shell_now:e}
 %   Execute commands through shell escape immediately.
+%
+%   For \LuaTeX{}, we use a pseudo-primitive to do the actual work.
 %    \begin{macrocode}
+%</tex>
+%<*lua>
+do
+  local os_exec = os.execute
+
+  local function shellescape(cmd)
+    local status,msg = os_exec(cmd)
+    if status == nil then
+      write_nl("log","runsystem(" .. cmd .. ")...(" .. msg .. ")\n")
+    elseif status == 0 then
+      write_nl("log","runsystem(" .. cmd .. ")...executed\n")
+    else
+      write_nl("log","runsystem(" .. cmd .. ")...failed " .. (msg or "") .. "\n")
+    end
+  end
+  luacmd("@@_shell_now:e", function()
+    shellescape(scan_string())
+  end, "global", "protected")
+%</lua>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<*tex>
 \sys_if_engine_luatex:TF
   {
     \cs_new_protected:Npn \sys_shell_now:n #1
-      {
-        \lua_now:e
-          { l3kernel.shellescape(" \lua_escape:e { \tl_to_str:n {#1} } ") }
-      }
+      { \@@_shell_now:e { \exp_not:n {#1} } }
   }
   {
     \cs_new_protected:Npn \sys_shell_now:n #1
@@ -662,19 +689,40 @@
       { \iow_now:Nn \c_@@_shell_stream_int {#1} }
   }
 \cs_generate_variant:Nn \sys_shell_now:n { x }
+%</tex>
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \begin{macro}{\sys_shell_shipout:n}
+% \begin{macro}{\@@_shell_shipout:e}
 %   Execute commands through shell escape at shipout.
+%
+%   For \LuaTeX, we use the same helper as above but delayed to using a late_lua whatsit.
 %    \begin{macrocode}
+%<*lua>
+  local whatsit_id = node.id'whatsit'
+  local latelua_sub = node.subtype'late_lua'
+  local node_new = node.direct.new
+  local setfield = node.direct.setwhatsitfield or node.direct.setfield
+  local node_write = node.direct.write
+
+  luacmd("@@_shell_shipout:e", function()
+    local cmd = scan_string()
+    local n = node_new(whatsit_id, latelua_sub)
+    setfield(n, 'data', function() shellescape(cmd) end)
+    node_write(n)
+  end, "global", "protected")
+end
+%</lua>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<*tex>
 \sys_if_engine_luatex:TF
   {
     \cs_new_protected:Npn \sys_shell_shipout:n #1
-      {
-        \lua_shipout_e:n
-          { l3kernel.shellescape(" \lua_escape:e { \tl_to_str:n {#1} } ") }
-      }
+    { \@@_shell_shipout:e { \exp_not:n {#1} } }
   }
   {
     \cs_new_protected:Npn \sys_shell_shipout:n #1
@@ -683,6 +731,7 @@
 \cs_generate_variant:Nn \sys_shell_shipout:n { x }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \subsection{Dynamic (every job) code}
 %
@@ -969,6 +1018,7 @@
 % \end{variable}
 %
 %    \begin{macrocode}
+%</tex>
 %</package>
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -737,12 +737,13 @@
 %   (not used by \LaTeX3).
 % \end{function}
 %
-% \begin{function}[updated = 2011-05-23, EXP,pTF]{\token_if_primitive:N}
+% \begin{function}[updated = 2020-09-11, EXP,pTF]{\token_if_primitive:N}
 %   \begin{syntax}
 %     \cs{token_if_primitive_p:N} \meta{token} \\
 %     \cs{token_if_primitive:NTF} \meta{token} \Arg{true code} \Arg{false code}
 %   \end{syntax}
-%   Tests if the \meta{token} is an engine primitive.
+%   Tests if the \meta{token} is an engine primitive. In \LuaTeX{}
+%   this includes primitive-like commands defined using |{token.set_lua}|.
 % \end{function}
 %
 % \section{Peeking ahead at the next token}
@@ -1112,6 +1113,10 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
+%<*tex>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
 %<@@=char>
 %    \end{macrocode}
 %
@@ -1454,37 +1459,26 @@
   \if_int_odd:w 0
       \sys_if_engine_luatex:T { 1 }
       \sys_if_engine_xetex:T { 1 } \exp_stop_f:
-    \sys_if_engine_luatex:TF
-      {
-        \cs_new:Npn \@@_generate_aux:nnw #1#2#3 \exp_end:
-          {
-            #3
-            \exp_after:wN \exp_after:wN \exp_after:wN \exp_end:
-            \lua_now:e { l3kernel.charcat(#1, #2) }
-          }
-      }
-      {
-        \cs_new:Npn \@@_generate_aux:nnw #1#2#3 \exp_end:
-          {
-            #3
-            \exp_after:wN \exp_end:
-            \tex_Ucharcat:D #1 \exp_stop_f: #2 \exp_stop_f:
-          }
-        \cs_if_exist:NF \tex_expanded:D
-          {
-            \cs_new_eq:NN \@@_generate_auxii:nnw \@@_generate_aux:nnw
-            \cs_gset:Npn \@@_generate_aux:nnw #1#2#3 \exp_end:
-              {
-                #3
-                \if_int_compare:w #2 = 13 \exp_stop_f:
-                  \__kernel_msg_expandable_error:nn { kernel } { char-active }
-                \else:
-                  \@@_generate_auxii:nnw {#1} {#2}
-                \fi:
-                \exp_end:
-              }
-          }
-      }
+      \cs_new:Npn \@@_generate_aux:nnw #1#2#3 \exp_end:
+        {
+          #3
+          \exp_after:wN \exp_end:
+          \tex_Ucharcat:D #1 \exp_stop_f: #2 \exp_stop_f:
+        }
+      \cs_if_exist:NF \tex_expanded:D
+        {
+          \cs_new_eq:NN \@@_generate_auxii:nnw \@@_generate_aux:nnw
+          \cs_gset:Npn \@@_generate_aux:nnw #1#2#3 \exp_end:
+            {
+              #3
+              \if_int_compare:w #2 = 13 \exp_stop_f:
+                \__kernel_msg_expandable_error:nn { kernel } { char-active }
+              \else:
+                \@@_generate_auxii:nnw {#1} {#2}
+              \fi:
+              \exp_end:
+            }
+        }
   \else:
 %    \end{macrocode}
 %   For engines where \tn{Ucharcat} isn't available or emulated, we have
@@ -2369,7 +2363,8 @@
 %     \@@_if_primitive_nullfont:N,
 %     \@@_if_primitive_loop:N,
 %     \@@_if_primitive:Nw,
-%     \@@_if_primitive_undefined:N}
+%     \@@_if_primitive_undefined:N,
+%     \@@_if_primitive_lua:N}
 %^^A See http://groups.google.com/group/comp.text.tex/browse_thread/thread/0a72666873f8753d#
 %
 %   We filter out macros first, because they cause endless trouble later
@@ -2414,68 +2409,143 @@
 %   \cs{tex_undefined:D}, and if it is |"| or a digit, then the token
 %   is not a primitive.
 %
+%   For \LuaTeX{} we use a different implementation which just looks at the
+%   command code for the token and compaes it to a list of non-primitives.
+%   Again, \tn{nullfont} is a special case because it is the only primitive
+%   with the normally non-primitive |set_font| command code.
+%
 %    \begin{macrocode}
-\tex_chardef:D \c_@@_A_int = `A ~ %
-\use:x
+\sys_if_engine_luatex:TF
   {
-    \prg_new_conditional:Npnn \exp_not:N \token_if_primitive:N ##1
-      { p , T , F , TF }
+%</tex>
+%<*lua>
+do
+  local get_next = token.get_next
+  local get_command = token.get_command
+  local get_index = token.get_index
+  local get_mode = token.get_mode or token.get_index
+  local cmd = token.command_id
+  local set_font = cmd'get_font'
+  local biggest_char = token.biggest_char()
+
+  local mode_below_biggest_char = {}
+  local index_not_nil = {}
+  local mode_not_null = {}
+  local non_primitive = {
+    [cmd'left_brace'] = true,
+    [cmd'right_brace'] = true,
+    [cmd'math_shift'] = true,
+    [cmd'mac_param'] = mode_below_biggest_char,
+    [cmd'sup_mark'] = true,
+    [cmd'sub_mark'] = true,
+    [cmd'endv'] = true,
+    [cmd'spacer'] = true,
+    [cmd'letter'] = true,
+    [cmd'other_char'] = true,
+    [cmd'tab_mark'] = mode_below_biggest_char,
+    [cmd'char_given'] = true,
+    [cmd'math_given'] = true,
+    [cmd'xmath_given'] = true,
+    [cmd'set_font'] = mode_not_null,
+    [cmd'undefined_cs'] = true,
+    [cmd'call'] = true,
+    [cmd'long_call'] = true,
+    [cmd'outer_call'] = true,
+    [cmd'long_outer_call'] = true,
+    [cmd'assign_glue'] = index_not_nil,
+    [cmd'assign_mu_glue'] = index_not_nil,
+    [cmd'assign_toks'] = index_not_nil,
+    [cmd'assign_int'] = index_not_nil,
+    [cmd'assign_attr'] = true,
+    [cmd'assign_dimen'] = index_not_nil,
+  }
+
+  luacmd("@@_if_primitive_lua:N", function()
+    local tok = get_next()
+    local is_non_primitive = non_primitive[get_command(tok)]
+    return put_next(
+           is_non_primitive == true
+             and false_tok
+        or is_non_primitive == nil
+             and true_tok
+        or is_non_primitive == mode_not_null
+             and (get_mode(tok) == 0 and true_tok or false_tok)
+        or is_non_primitive == index_not_nil
+             and (get_index(tok) and false_tok or true_tok)
+        or is_non_primitive == mode_below_biggest_char
+             and (get_mode(tok) > biggest_char and true_tok or false_tok))
+  end, "global")
+end
+%</lua>
+%<*tex>
+    \prg_new_conditional:Npnn \token_if_primitive:N #1 { p , T , F , TF }
       {
-        \exp_not:N \token_if_macro:NTF ##1
-          \exp_not:N \prg_return_false:
-          {
-            \exp_not:N \exp_after:wN \exp_not:N \@@_if_primitive:NNw
-            \exp_not:N \token_to_meaning:N ##1
-              \tl_to_str:n { : : : } \s_@@_stop ##1
-          }
+        \@@_if_primitive_lua:N #1
       }
-    \cs_new:Npn \exp_not:N \@@_if_primitive:NNw
-      ##1##2 ##3 \c_colon_str ##4 \s_@@_stop
+  }
+  {
+    \tex_chardef:D \c_@@_A_int = `A ~ %
+    \use:x
       {
-        \exp_not:N \tl_if_empty:oTF
-          { \exp_not:N \@@_if_primitive_space:w ##3 ~ }
+        \prg_new_conditional:Npnn \exp_not:N \token_if_primitive:N ##1
+          { p , T , F , TF }
           {
-            \exp_not:N \@@_if_primitive_loop:N ##3
-              \c_colon_str \s_@@_stop
+            \exp_not:N \token_if_macro:NTF ##1
+              \exp_not:N \prg_return_false:
+              {
+                \exp_not:N \exp_after:wN \exp_not:N \@@_if_primitive:NNw
+                \exp_not:N \token_to_meaning:N ##1
+                  \tl_to_str:n { : : : } \s_@@_stop ##1
+              }
           }
-          { \exp_not:N \@@_if_primitive_nullfont:N }
+        \cs_new:Npn \exp_not:N \@@_if_primitive:NNw
+          ##1##2 ##3 \c_colon_str ##4 \s_@@_stop
+          {
+            \exp_not:N \tl_if_empty:oTF
+              { \exp_not:N \@@_if_primitive_space:w ##3 ~ }
+              {
+                \exp_not:N \@@_if_primitive_loop:N ##3
+                  \c_colon_str \s_@@_stop
+              }
+              { \exp_not:N \@@_if_primitive_nullfont:N }
+          }
       }
+    \cs_new:Npn \@@_if_primitive_space:w #1 ~ { }
+    \cs_new:Npn \@@_if_primitive_nullfont:N #1
+      {
+        \if_meaning:w \tex_nullfont:D #1
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
+    \cs_new:Npn \@@_if_primitive_loop:N #1
+      {
+        \if_int_compare:w `#1 < \c_@@_A_int %
+          \exp_after:wN \@@_if_primitive:Nw
+          \exp_after:wN #1
+        \else:
+          \exp_after:wN \@@_if_primitive_loop:N
+        \fi:
+      }
+    \cs_new:Npn \@@_if_primitive:Nw #1 #2 \s_@@_stop
+      {
+        \if:w : #1
+          \exp_after:wN \@@_if_primitive_undefined:N
+        \else:
+          \prg_return_false:
+          \exp_after:wN \use_none:n
+        \fi:
+      }
+    \cs_new:Npn \@@_if_primitive_undefined:N #1
+      {
+        \if_cs_exist:N #1
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
   }
-\cs_new:Npn \@@_if_primitive_space:w #1 ~ { }
-\cs_new:Npn \@@_if_primitive_nullfont:N #1
-  {
-    \if_meaning:w \tex_nullfont:D #1
-      \prg_return_true:
-    \else:
-      \prg_return_false:
-    \fi:
-  }
-\cs_new:Npn \@@_if_primitive_loop:N #1
-  {
-    \if_int_compare:w `#1 < \c_@@_A_int %
-      \exp_after:wN \@@_if_primitive:Nw
-      \exp_after:wN #1
-    \else:
-      \exp_after:wN \@@_if_primitive_loop:N
-    \fi:
-  }
-\cs_new:Npn \@@_if_primitive:Nw #1 #2 \s_@@_stop
-  {
-    \if:w : #1
-      \exp_after:wN \@@_if_primitive_undefined:N
-    \else:
-      \prg_return_false:
-      \exp_after:wN \use_none:n
-    \fi:
-  }
-\cs_new:Npn \@@_if_primitive_undefined:N #1
-  {
-    \if_cs_exist:N #1
-      \prg_return_true:
-    \else:
-      \prg_return_false:
-    \fi:
-  }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
@@ -2869,6 +2939,10 @@
 % \end{macro}
 %
 %    \begin{macrocode}
+%</tex>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
 %</package>
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-09-06}
+% \date{Released 2020-09-24}
 %
 % \maketitle
 %
@@ -97,22 +97,9 @@
         {
           \exp_not:N \tex_unexpanded:D \exp_not:N \exp_after:wN
             {
-              \sys_if_engine_luatex:TF
-                {
-                  \exp_not:N \tex_directlua:D
-                    {
-                      l3kernel.charcat
-                        (
-                          \exp_not:N \tex_number:D #1 ,
-                          \exp_not:N \tex_the:D \tex_catcode:D #1
-                        )
-                    }
-                }
-                {
-                  \exp_not:N \tex_Ucharcat:D
-                    #1 ~
-                    \tex_catcode:D #1 ~
-                }
+              \exp_not:N \tex_Ucharcat:D
+                #1 ~
+                \tex_catcode:D #1 ~
             }
         } 
 %    \end{macrocode}

Modified: trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvipdfmx.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvipdfmx.def	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvipdfmx.def	2020-09-24 20:46:14 UTC (rev 56424)
@@ -25,7 +25,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-dvipdfmx.def}{2020-09-11}{}
+  {l3backend-dvipdfmx.def}{2020-09-24}{}
   {L3 backend support: dvipdfmx}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -92,6 +92,7 @@
     \__kernel_backend_literal:n { pdf: bc ~ #1 }
     \group_insert_after:N \__color_backend_reset:
   }
+\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn
 \cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5
   {
     \pdf_object_now:nx { dict }
@@ -104,7 +105,7 @@
       }
     \__color_backend_separation_init:n
       {
-        /Separation
+        /Separation ~
         / \str_convert_pdfname:n {#1} ~ #2 ~
         \pdf_object_last:
       }
@@ -115,7 +116,7 @@
   {
     \__kernel_backend_literal:x
       {
-        pdf:obj ~ @color \int_use:N \g__color_separation_int \c_space_tl
+        pdf:obj ~ @color \int_use:N \g__color_model_int \c_space_tl
           [#1]
       }
   }
@@ -146,6 +147,47 @@
     \cs_gset_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3
       { }
   }
+\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3
+  {
+    \pdf_object_now:nx { stream }
+      {
+        {
+          /FunctionType ~ 4 ~
+          /Domain ~
+            [ ~
+              \prg_replicate:nn
+                { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop }
+                { 0 ~ 1 ~ } ~
+            ] ~
+          /Range ~
+            [ ~
+              \str_case:nn {#2}
+                {
+                  { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                  { /DeviceGray } { 0 ~ 1 }
+                  { /DeviceRGB }  { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                } ~
+            ]
+        }
+        {#3}
+     }
+    \__color_backend_separation_init:n
+      {
+        /DeviceN ~
+        [ ~ #1 ~ ] ~
+        #2 ~
+        \pdf_object_last:
+      }
+  }
+\cs_if_exist:NF \pdf_object_now:nn
+  { \cs_gset_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 { } }
+\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop
+  {
+    + 1
+    \tl_if_blank:nF {#2}
+      { \__color_backend_devicen_init:w #2 \s__color_stop }
+  }
+\cs_new_eq:NN \__color_backend_devicen_init:n \__color_backend_separation_init:n
 \cs_new_protected:Npn \__color_backend_fill_cmyk:n #1
   { \__kernel_backend_literal_pdf:n { #1 ~ k } }
 \cs_new_protected:Npn \__color_backend_fill_gray:n #1
@@ -162,6 +204,8 @@
   { \__kernel_backend_literal_pdf:n { /#1 ~ cs ~ #2 ~ scn } }
 \cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2
   { \__kernel_backend_literal_pdf:n { /#1 ~ CS ~ #2 ~ SCN } }
+\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn
+\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn
 %% File: l3backend-box.dtx
 \cs_new_protected:Npn \__box_backend_clip:N #1
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvips.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvips.def	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvips.def	2020-09-24 20:46:14 UTC (rev 56424)
@@ -25,7 +25,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-dvips.def}{2020-09-11}{}
+  {l3backend-dvips.def}{2020-09-24}{}
   {L3 backend support: dvips}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -112,6 +112,7 @@
   { \__kernel_backend_literal:n { color~pop } }
 \cs_new_protected:Npn \__color_backend_select_separation:nn #1#2
   { \__color_backend_select:n { separation ~ #1 ~ #2 } }
+\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn
 \cs_new_protected:Npx \__color_backend_separation_init:nnnnn #1#2#3#4#5
   {
     \bool_if:NT \g__kernel_backend_header_bool
@@ -132,7 +133,7 @@
       {
         !
         TeXDict ~ begin ~
-        /color \int_use:N \g__color_separation_int
+        /color \int_use:N \g__color_model_int
           {
             [ ~
               /Separation ~ ( \str_convert_pdfname:n {#1} ) ~
@@ -262,6 +263,24 @@
       { 100 ~ 0 ~ 0 }
       {#3}
   }
+\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3
+  {
+    \__kernel_backend_literal:e
+      {
+        !
+        TeXDict ~ begin ~
+        /color \int_use:N \g__color_model_int
+          {
+            [ ~
+              /DeviceN ~
+              [ ~ #1 ~ ] ~
+              #2 ~
+              { ~ #3 ~ } ~
+            ] ~ setcolorspace
+          } ~ def ~
+        end
+      }
+  }
 \cs_new_protected:Npn \__color_backend_fill_cmyk:n #1
   { \__kernel_backend_postscript:n { /color.fc { #1 ~ setcmykcolor } def } }
 \cs_new_protected:Npn \__color_backend_fill_gray:n #1
@@ -278,6 +297,8 @@
   { \__kernel_backend_postscript:n { /color.fc { #1 } def } }
 \cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2
   { \__kernel_backend_postscript:n { /color.sc { #1 } def } }
+\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn
+\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn
 %% File: l3backend-box.dtx
 \cs_new_protected:Npn \__box_backend_clip:N #1
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvisvgm.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvisvgm.def	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-dvisvgm.def	2020-09-24 20:46:14 UTC (rev 56424)
@@ -25,7 +25,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-dvisvgm.def}{2020-09-11}{}
+  {l3backend-dvisvgm.def}{2020-09-24}{}
   {L3 backend support: dvisvgm}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -121,6 +121,7 @@
 \cs_new_protected:Npn \__color_backend_reset:
   { \__kernel_backend_literal:n { color~pop } }
 \cs_new_protected:Npn \__color_backend_select_separation:nn #1#2 { }
+\cs_new_protected:Npn \__color_backend_select_devicen:nn #1#2 { }
 \cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5 { }
 \cs_new_protected:Npn \__color_backend_separation_init_CIELAB:nnnnnn #1#2#3 { }
 \cs_new_protected:Npn \__color_backend_fill_cmyk:n #1
@@ -185,10 +186,10 @@
          "
       }
   }
-\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2
-  { }
-\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2
-  { }
+\cs_new_protected:Npn \__color_backend_fill_separation:nn #1#2 { }
+\cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2 { }
+\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn
+\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn
 %% File: l3backend-box.dtx
 \cs_new_protected:Npn \__box_backend_clip:N #1
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-luatex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-luatex.def	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-luatex.def	2020-09-24 20:46:14 UTC (rev 56424)
@@ -25,7 +25,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-luatex.def}{2020-09-11}{}
+  {l3backend-luatex.def}{2020-09-24}{}
   {L3 backend support: PDF output (LuaTeX)}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -123,6 +123,7 @@
   }
 \cs_new_protected:Npn \__color_backend_select_separation:nn #1#2
   { \__color_backend_select:n { /#1 ~ cs ~ /#1 ~ CS ~ #2 ~ scn ~ #2 ~ SCN } }
+\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn
 \cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5
   {
     \pdf_object_now:nx { dict }
@@ -135,7 +136,7 @@
       }
     \__color_backend_separation_init:n
       {
-        /Separation
+        /Separation ~
         / \str_convert_pdfname:n {#1} ~ #2 ~
         \pdf_object_last:
       }
@@ -143,7 +144,7 @@
       {
         \pdfcoredict_gput:nnn
           { Page / Resources / ColorSpace }
-          { color \int_use:N \g__color_separation_int }
+          { color \int_use:N \g__color_model_int }
           { \pdf_object_last: }
       }
   }
@@ -180,6 +181,54 @@
     \cs_gset_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3
       { }
   }
+\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3
+  {
+    \pdf_object_now:nx { stream }
+      {
+        {
+          /FunctionType ~ 4 ~
+          /Domain ~
+            [ ~
+              \prg_replicate:nn
+                { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop }
+                { 0 ~ 1 ~ } ~
+            ] ~
+          /Range ~
+            [ ~
+              \str_case:nn {#2}
+                {
+                  { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                  { /DeviceGray } { 0 ~ 1 }
+                  { /DeviceRGB }  { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                } ~
+            ]
+        }
+        {#3}
+     }
+    \__color_backend_separation_init:n
+      {
+        /DeviceN ~
+        [ ~ #1 ~ ] ~
+        #2 ~
+        \pdf_object_last:
+      }
+    \use:x
+      {
+        \pdfcoredict_gput:nnn
+          { Page / Resources / ColorSpace }
+          { color \int_use:N \g__color_model_int }
+          { \pdf_object_last: }
+      }
+  }
+\cs_if_exist:NF \pdf_object_now:nn
+  { \cs_gset_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 { } }
+\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop
+  {
+    + 1
+    \tl_if_blank:nF {#2}
+      { \__color_backend_devicen_init:w #2 \s__color_stop }
+  }
+\cs_new_eq:NN \__color_backend_devicen_init:n \__color_backend_separation_init:n
 \cs_new_protected:Npn \__color_backend_fill_cmyk:n #1
   { \__kernel_backend_literal_pdf:n { #1 ~ k } }
 \cs_new_protected:Npn \__color_backend_fill_gray:n #1
@@ -196,6 +245,8 @@
   { \__kernel_backend_literal_pdf:n { /#1 ~ cs ~ #2 ~ scn } }
 \cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2
   { \__kernel_backend_literal_pdf:n { /#1 ~ CS ~ #2 ~ SCN } }
+\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn
+\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn
 %% File: l3backend-box.dtx
 \cs_new_protected:Npn \__box_backend_clip:N #1
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def	2020-09-24 20:46:14 UTC (rev 56424)
@@ -25,7 +25,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-pdftex.def}{2020-09-11}{}
+  {l3backend-pdftex.def}{2020-09-24}{}
   {L3 backend support: PDF output (pdfTeX)}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -123,6 +123,7 @@
   }
 \cs_new_protected:Npn \__color_backend_select_separation:nn #1#2
   { \__color_backend_select:n { /#1 ~ cs ~ /#1 ~ CS ~ #2 ~ scn ~ #2 ~ SCN } }
+\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn
 \cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5
   {
     \pdf_object_now:nx { dict }
@@ -135,7 +136,7 @@
       }
     \__color_backend_separation_init:n
       {
-        /Separation
+        /Separation ~
         / \str_convert_pdfname:n {#1} ~ #2 ~
         \pdf_object_last:
       }
@@ -143,7 +144,7 @@
       {
         \pdfcoredict_gput:nnn
           { Page / Resources / ColorSpace }
-          { color \int_use:N \g__color_separation_int }
+          { color \int_use:N \g__color_model_int }
           { \pdf_object_last: }
       }
   }
@@ -180,6 +181,54 @@
     \cs_gset_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3
       { }
   }
+\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3
+  {
+    \pdf_object_now:nx { stream }
+      {
+        {
+          /FunctionType ~ 4 ~
+          /Domain ~
+            [ ~
+              \prg_replicate:nn
+                { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop }
+                { 0 ~ 1 ~ } ~
+            ] ~
+          /Range ~
+            [ ~
+              \str_case:nn {#2}
+                {
+                  { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                  { /DeviceGray } { 0 ~ 1 }
+                  { /DeviceRGB }  { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                } ~
+            ]
+        }
+        {#3}
+     }
+    \__color_backend_separation_init:n
+      {
+        /DeviceN ~
+        [ ~ #1 ~ ] ~
+        #2 ~
+        \pdf_object_last:
+      }
+    \use:x
+      {
+        \pdfcoredict_gput:nnn
+          { Page / Resources / ColorSpace }
+          { color \int_use:N \g__color_model_int }
+          { \pdf_object_last: }
+      }
+  }
+\cs_if_exist:NF \pdf_object_now:nn
+  { \cs_gset_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 { } }
+\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop
+  {
+    + 1
+    \tl_if_blank:nF {#2}
+      { \__color_backend_devicen_init:w #2 \s__color_stop }
+  }
+\cs_new_eq:NN \__color_backend_devicen_init:n \__color_backend_separation_init:n
 \cs_new_protected:Npn \__color_backend_fill_cmyk:n #1
   { \__kernel_backend_literal_pdf:n { #1 ~ k } }
 \cs_new_protected:Npn \__color_backend_fill_gray:n #1
@@ -196,6 +245,8 @@
   { \__kernel_backend_literal_pdf:n { /#1 ~ cs ~ #2 ~ scn } }
 \cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2
   { \__kernel_backend_literal_pdf:n { /#1 ~ CS ~ #2 ~ SCN } }
+\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn
+\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn
 %% File: l3backend-box.dtx
 \cs_new_protected:Npn \__box_backend_clip:N #1
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-xetex.def
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-xetex.def	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3backend/l3backend-xetex.def	2020-09-24 20:46:14 UTC (rev 56424)
@@ -25,7 +25,7 @@
 %% 
 %% File: l3backend-basics.dtx
 \ProvidesExplFile
-  {l3backend-xetex.def}{2020-09-11}{}
+  {l3backend-xetex.def}{2020-09-24}{}
   {L3 backend support: XeTeX}
 \cs_if_exist:NTF \__kernel_dependency_version_check:nn
   {
@@ -92,6 +92,7 @@
     \__kernel_backend_literal:n { pdf: bc ~ #1 }
     \group_insert_after:N \__color_backend_reset:
   }
+\cs_new_eq:NN \__color_backend_select_devicen:nn \__color_backend_select_separation:nn
 \cs_new_protected:Npn \__color_backend_separation_init:nnnnn #1#2#3#4#5
   {
     \pdf_object_now:nx { dict }
@@ -104,7 +105,7 @@
       }
     \__color_backend_separation_init:n
       {
-        /Separation
+        /Separation ~
         / \str_convert_pdfname:n {#1} ~ #2 ~
         \pdf_object_last:
       }
@@ -115,7 +116,7 @@
   {
     \__kernel_backend_literal:x
       {
-        pdf:obj ~ @color \int_use:N \g__color_separation_int \c_space_tl
+        pdf:obj ~ @color \int_use:N \g__color_model_int \c_space_tl
           [#1]
       }
   }
@@ -146,6 +147,47 @@
     \cs_gset_protected:Npn \__color_backend_separation_init_CIELAB:nnn #1#2#3
       { }
   }
+\cs_new_protected:Npn \__color_backend_devicen_init:nnn #1#2#3
+  {
+    \pdf_object_now:nx { stream }
+      {
+        {
+          /FunctionType ~ 4 ~
+          /Domain ~
+            [ ~
+              \prg_replicate:nn
+                { 0 \__color_backend_devicen_init:w #1 ~ \s__color_stop }
+                { 0 ~ 1 ~ } ~
+            ] ~
+          /Range ~
+            [ ~
+              \str_case:nn {#2}
+                {
+                  { /DeviceCMYK } { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                  { /DeviceGray } { 0 ~ 1 }
+                  { /DeviceRGB }  { 0 ~ 1 ~ 0 ~ 1 ~ 0 ~ 1 }
+                } ~
+            ]
+        }
+        {#3}
+     }
+    \__color_backend_separation_init:n
+      {
+        /DeviceN ~
+        [ ~ #1 ~ ] ~
+        #2 ~
+        \pdf_object_last:
+      }
+  }
+\cs_if_exist:NF \pdf_object_now:nn
+  { \cs_gset_protected:Npn \__color_backend_devicen_init:nnn #1#2#3 { } }
+\cs_new:Npn \__color_backend_devicen_init:w #1 ~ #2 \s__color_stop
+  {
+    + 1
+    \tl_if_blank:nF {#2}
+      { \__color_backend_devicen_init:w #2 \s__color_stop }
+  }
+\cs_new_eq:NN \__color_backend_devicen_init:n \__color_backend_separation_init:n
 \cs_new_protected:Npn \__color_backend_fill_cmyk:n #1
   { \__kernel_backend_literal_pdf:n { #1 ~ k } }
 \cs_new_protected:Npn \__color_backend_fill_gray:n #1
@@ -162,6 +204,8 @@
   { \__kernel_backend_literal_pdf:n { /#1 ~ cs ~ #2 ~ scn } }
 \cs_new_protected:Npn \__color_backend_stroke_separation:nn #1#2
   { \__kernel_backend_literal_pdf:n { /#1 ~ CS ~ #2 ~ SCN } }
+\cs_new_eq:NN \__color_backend_fill_devicen:nn \__color_backend_fill_separation:nn
+\cs_new_eq:NN \__color_backend_stroke_devicen:nn \__color_backend_stroke_separation:nn
 %% File: l3backend-box.dtx
 \cs_new_protected:Npn \__box_backend_clip:N #1
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/l3benchmark/l3benchmark.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/l3benchmark/l3benchmark.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/l3benchmark/l3benchmark.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,12 +20,31 @@
 %% 
 %% File: l3benchmark.dtx
 \RequirePackage{expl3}
-\ProvidesExplPackage{l3benchmark}{2020-09-11}{}
+\ProvidesExplPackage{l3benchmark}{2020-09-24}{}
   {L3 Experimental benchmarking}
 \sys_if_engine_luatex:TF
   {
+    \cs_new:Npn \__sys_elapsedtime: { }
+    \cs_new:Npn \__sys_resettimer: { }
+    \lua_now:n
+      {
+        local~gettimeofday = os.gettimeofday~
+        local~epoch = gettimeofday() - os.clock()~
+        local~write = tex.write~
+        local~tointeger = math.tointeger~
+        local~id = luatexbase.new_luafunction'__sys_elapsedtime:'
+        lua.get_functions_table()[id] = function()
+        write(tointeger((gettimeofday() - epoch)*65536 // 1))
+        end~
+        token.set_lua('__sys_elapsedtime:', id, 'global')
+        id = luatexbase.new_luafunction'__sys_resettimer:'
+        lua.get_functions_table()[id] = function()
+          epoch = gettimeofday()
+        end~
+        token.set_lua('__sys_resettimer:', id, 'global', 'protected')
+      }
     \cs_new:Npn \sys_timer:
-      { \lua_now:n { l3kernel.elapsedtime() } }
+      { \__sys_elapsedtime: }
   }
   {
     \cs_if_exist:NT \tex_elapsedtime:D
@@ -41,7 +60,7 @@
     \sys_if_engine_luatex:TF
       {
         \cs_new_protected:Npn \sys_gzero_timer:
-          { \lua_now:n { l3kernel.resettimer() } }
+          { \__sys_resettimer: }
       }
       { \cs_new_protected:Npn \sys_gzero_timer: { \tex_resettimer:D } }
   }

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/l3color/l3color.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/l3color/l3color.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/l3color/l3color.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,8 +20,9 @@
 %% 
 %% File: l3color.dtx
 \RequirePackage{expl3}
-\ProvidesExplPackage{l3color}{2020-09-11}{}
+\ProvidesExplPackage{l3color}{2020-09-24}{}
   {L3 Experimental color support}
+\int_new:N \l__color_internal_int
 \tl_new:N \l__color_internal_tl
 \scan_new:N \s__color_mark
 \prg_new_conditional:Npnn \__color_if_defined:n #1 { T, F, TF }
@@ -698,7 +699,19 @@
 \cs_new_protected:cpn { __color_export_space-sep-rgb:Nw } #1#2 \s__color_stop
   { \tl_set:Nx #1 {#2} }
 \prop_new:N \l__color_internal_prop
-\int_new:N \g__color_separation_int
+\int_new:N \g__color_model_int
+\tl_const:Nn \c__color_fallback_cmyk_tl { 0 ~ 0 ~ 0 ~ 1 }
+\tl_const:Nn \c__color_fallback_gray_tl { 1 }
+\tl_const:Nn \c__color_fallback_rgb_tl { 1 ~ 1 ~ 1 }
+\prop_new:N \g__color_colorants_prop
+\prop_gput:Nnn \g__color_colorants_prop { black }   { Black }
+\prop_gput:Nnn \g__color_colorants_prop { blue }    { Blue }
+\prop_gput:Nnn \g__color_colorants_prop { cyan }    { Cyan }
+\prop_gput:Nnn \g__color_colorants_prop { green }   { Green }
+\prop_gput:Nnn \g__color_colorants_prop { magenta } { Magenta }
+\prop_gput:Nnn \g__color_colorants_prop { none }    { None }
+\prop_gput:Nnn \g__color_colorants_prop { red }     { Red }
+\prop_gput:Nnn \g__color_colorants_prop { yellow }  { Yellow }
 \tl_const:Nn \c__color_model_whitepoint_CIELAB_a_tl      { 1.0985 ~ 1 ~ 0.3558 }
 \tl_const:Nn \c__color_model_whitepoint_CIELAB_b_tl      { 0.9807 ~ 1 ~ 1.1822 }
 \tl_const:Nn \c__color_model_whitepoint_CIELAB_e_tl      { 1 ~ 1 ~ 1 }
@@ -707,6 +720,19 @@
 \tl_const:cn { c__color_model_whitepoint_CIELAB_d65_tl } { 0.9504 ~ 1 ~ 1.0888 }
 \tl_const:cn { c__color_model_whitepoint_CIELAB_d75_tl } { 0.9497 ~ 1 ~ 1.2261 }
 \tl_const:Nn \c__color_model_range_CIELAB_tl { 0 ~ 100 ~ -128 ~ 127 ~ -128 ~ 127 }
+\prop_new:N \g__color_alternative_model_prop
+\clist_map_inline:nn { cyan , magenta , yellow , black }
+  { \prop_gput:Nnn \g__color_alternative_model_prop {#1} { cmyk } }
+\clist_map_inline:nn { red , green , blue }
+  { \prop_gput:Nnn \g__color_alternative_model_prop {#1} { rgb } }
+\prop_new:N \g__color_alternative_values_prop
+\prop_gput:Nnn \g__color_alternative_values_prop { cyan }    {  1 , 0 , 0 , 0 }
+\prop_gput:Nnn \g__color_alternative_values_prop { magenta } {  0 , 1 , 0 , 0 }
+\prop_gput:Nnn \g__color_alternative_values_prop { yellow }  {  0 , 0 , 1 , 0 }
+\prop_gput:Nnn \g__color_alternative_values_prop { black }   {  0 , 0 , 0 , 1 }
+\prop_gput:Nnn \g__color_alternative_values_prop { red }   {  1 , 0 , 0 }
+\prop_gput:Nnn \g__color_alternative_values_prop { green } {  0 , 1 , 0 }
+\prop_gput:Nnn \g__color_alternative_values_prop { blue }  {  0 , 0 , 1 }
 \cs_new_protected:Npn \color_model_new:nnn #1#2#3
   {
     \exp_args:Nee \__color_model_new:nnn
@@ -779,7 +805,7 @@
 \cs_new_protected:Npn \__color_model_separation:w
   #1 , #2 , #3 , #4 , #5 \s__color_stop #6#7#8
   {
-    \int_gincr:N \g__color_separation_int
+    \int_gincr:N \g__color_model_int
     \tl_const:cn { c__color_fallback_ #6 _tl } { 1 }
     \cs_new_eq:cN { __color_parse_mix_ #6 :nw } \__color_parse_mix_gray:nw
     \cs_new:cpn { __color_parse_model_ #6 :w } ##1 , ##2 \s__color_stop
@@ -789,11 +815,14 @@
         \cs_new_protected:cpx { __color_backend_ ##1 _ #6 :n } ####1
           {
             \exp_not:c { __color_backend_ ##1 _ separation:nn }
-              { color \int_use:N \g__color_separation_int } {####1}
+              { color \int_use:N \g__color_model_int } {####1}
           }
       }
     \use:c { __color_model_separation_ #8 :nnnnnn }
       {#6} {#7} {#1} {#2} {#3} {#4}
+    \prop_gput:Nnn \g__color_alternative_model_prop {#6} {#8}
+    \prop_gput:Nnx \g__color_colorants_prop {#6}
+      { \str_convert_pdfname:n {#7} }
     \cs_new_protected:cpx { __color_model_ #6 _white: }
       {
         \prop_put:Nnn \exp_not:N \l__color_named_white_prop {#6} { 0 }
@@ -813,6 +842,7 @@
       }
     \__color_model_convert:nnn {#1} { cmyk } { rgb }
     \__color_model_convert:nnn {#1} { cmyk } { gray }
+    \prop_gput:Nnn \g__color_alternative_values_prop {#1} { #3 , #4 , #5 , #6 }
     \__color_backend_separation_init:nnnnn {#2} { /DeviceCMYK } { }
       { 0 ~ 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 ~ #6 }
   }
@@ -826,6 +856,7 @@
       }
     \__color_model_convert:nnn {#1} { rgb } { cmyk }
     \__color_model_convert:nnn {#1} { rgb } { gray }
+    \prop_gput:Nnn \g__color_alternative_values_prop {#1} { #3 , #4 , #5 }
     \__color_backend_separation_init:nnnnn {#2} { /DeviceRGB } { }
       { 0 ~ 0 ~ 0 } { #3 ~ #4 ~ #5 }
   }
@@ -846,6 +877,7 @@
         \fp_eval:n {##1 * #3} ~
         \fp_eval:n {##1 * #3}
       }
+    \prop_gput:Nnn \g__color_alternative_values_prop {#1} {#3}
     \__color_backend_separation_init:nnnnn {#2} { /DeviceGray } { } { 0 } {#3}
   }
 \cs_new_protected:Npn \__color_model_convert:nnn #1#2#3
@@ -887,6 +919,393 @@
           { unknown-CIELAB-illuminant } {#1}
       }
   }
+\cs_new_protected:Npn \__color_model_devicen:n #1
+  {
+    \prop_get:NnNTF \l__color_internal_prop { names }
+      \l__color_internal_tl
+      {
+        \exp_args:NV \__color_model_devicen:nn
+          \l__color_internal_tl {#1}
+      }
+      {
+        \__kernel_msg_error:nnn { color }
+          { DeviceN-requires-names } {#1}
+      }
+  }
+\cs_new_protected:Npn \__color_model_devicen:nn #1#2
+  {
+    \tl_clear:N \l__color_model_tl
+    \clist_map_inline:nn {#1}
+      {
+        \prop_get:NnNTF \g__color_alternative_model_prop {##1}
+          \l__color_internal_tl
+          {
+            \tl_if_empty:NTF \l__color_model_tl
+              { \tl_set_eq:NN \l__color_model_tl \l__color_internal_tl }
+              {
+                \str_if_eq:VVF \l__color_model_tl \l__color_internal_tl
+                  {
+                    \__kernel_msg_error:nnn { color }
+                      { DeviceN-inconsistent-alternative }
+                      {#2}
+                    \clist_map_break:n { \use_none:nnnn }
+                  }
+               }
+          }
+          {
+            \str_if_eq:nnF {##1} { none }
+              {
+                \__kernel_msg_error:nnn { color }
+                  { DeviceN-no-alternative }
+                  {#2}
+              }
+          }
+      }
+    \tl_if_empty:NTF \l__color_model_tl
+      {
+        \__kernel_msg_error:nnn { color }
+          { DeviceN-no-alternative } {#2}
+      }
+      { \exp_args:NV \__color_model_devicen:nnn \l__color_model_tl {#1} {#2} }
+  }
+\cs_new_protected:Npn \__color_model_devicen:nnn #1#2#3
+  {
+    \exp_args:Nx \__color_model_devicen:nnnn
+      { \clist_count:n {#2} } {#1} {#2} {#3}
+  }
+\cs_new_protected:Npn \__color_model_devicen:nnnn #1#2#3#4
+  {
+    \int_gincr:N \g__color_model_int
+    \tl_const:cx { c__color_fallback_ #4 _tl }
+      { \prg_replicate:nn {#1} { 1 ~ } }
+    \cs_if_exist_use:cF { __color_model_devicen_parse_ #1 :nn }
+      { \__color_model_devicen_parse_generic:nn }
+        {#4} {#1}
+    \clist_map_inline:nn { fill , stroke , select }
+      {
+        \cs_new_protected:cpx { __color_backend_ ##1 _ #4 :n } ####1
+          {
+            \exp_not:c { __color_backend_ ##1 _ devicen:nn }
+              { color \int_use:N \g__color_model_int } {####1}
+          }
+      }
+    \cs_new_protected:cpx { __color_model_ #4 _white: }
+      {
+        \prop_put:Nnn \exp_not:N \l__color_named_white_prop {#4}
+          { \prg_replicate:nn {#1} { 0 ~ } }
+        \exp_not:N \int_compare:nNnF { \tex_currentgrouplevel:D } = 0
+          { \group_insert_after:N \exp_not:c { __color_model_ #4 _ white: } }
+      }
+    \use:c { __color_model_ #4 _white: }
+    \__color_model_devicen_init:nnn {#1} {#2} {#3}
+    \__color_model_devicen_convert:nnn {#4} {#2} {#3}
+  }
+\cs_new_protected:cpn { __color_model_devicen_parse_1:nn } #1#2
+  {
+    \cs_new:cpn { __color_parse_model_ #1 :w  } ##1 , ##2 \s__color_stop
+      { {#1} { \__color_parse_number:n {##1} } }
+    \cs_new_eq:cN { __color_parse_mix_ #1 :nw  } \__color_parse_mix_gray:nw
+  }
+\cs_new_protected:cpn { __color_model_devicen_parse_2:nn } #1#2
+  {
+    \cs_new:cpn { __color_parse_model_ #1 :w  } ##1 , ##2 , ##3 \s__color_stop
+      { {#1} { \__color_parse_number:n {##1} ~ \__color_parse_number:n {##2} } }
+    \cs_new:cpn { __color_parse_mix_ #1 :nw }
+      ##1##2 ~ ##3 \s__color_mark ##4 ~ ##5 \s__color_stop
+      {
+        \fp_eval:n { ##2 * ##1 + ##4 * ( 1 - ##1 ) } \c_space_tl
+        \fp_eval:n { ##3 * ##1 + ##5 * ( 1 - ##1 ) }
+      }
+  }
+\cs_new_protected:cpn { __color_model_devicen_parse_3:nn } #1#2
+  {
+    \cs_new:cpn { __color_parse_model_ #1 :w  } ##1 , ##2 , ##3 , ##4 \s__color_stop
+      {
+        {#1}
+        {
+          \__color_parse_number:n {##1} ~
+          \__color_parse_number:n {##2} ~
+          \__color_parse_number:n {##3}
+        }
+      }
+    \cs_new_eq:cN { __color_parse_mix_ #1 :nw  } \__color_parse_mix_rgb:nw
+  }
+\cs_new_protected:cpn { __color_model_devicen_parse_4:nn } #1#2
+  {
+    \cs_new:cpn { __color_parse_model_ #1 :w  }
+      ##1 , ##2 , ##3 , ##4 , ##5 \s__color_stop
+      {
+        {#1}
+        {
+          \__color_parse_number:n {##1} ~
+          \__color_parse_number:n {##2} ~
+          \__color_parse_number:n {##3} ~
+          \__color_parse_number:n {##4}
+        }
+      }
+  \cs_new_eq:cN { __color_parse_mix_ #1 :nw } \__color_parse_mix_cmyk:nw
+  }
+\cs_new_protected:Npn \__color_model_devicen_parse_generic:nn #1#2
+  {
+    \cs_new:cpn { __color_parse_model_ #1 :w  } ##1 , ##2 \s__color_stop
+      {
+        {#1}
+        { \__color_model_devicen_parse:nw {#2} ##1 , ##2 , \q_nil , \s__color_stop }
+      }
+    \cs_new:cpx { __color_parse_mix_ #1 :nw }
+      ##1 ##2 \s__color_mark ##3 \s__color_stop
+      {
+        \exp_not:N \__color_model_devicen_mix:nw {##1}
+          ##2 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s__color_mark
+          ##3 \c_space_tl \exp_not:N \q_nil \c_space_tl \exp_not:N \s__color_stop
+      }
+  }
+\cs_new:Npn \__color_model_devicen_parse:nw #1#2 , #3 \s__color_stop
+  {
+    \int_compare:nNnT {#1} > 0
+      {
+        \quark_if_nil:nTF {#2}
+          { \prg_replicate:nn {#1} { 0 ~ } }
+          {
+            \__color_parse_number:n {#2}
+            \int_compare:nNnT {#1} > 1 { ~ }
+            \exp_args:Nf \__color_model_devicen_parse:nw
+              { \int_eval:n { #1 - 1 } } #3 \s__color_stop
+          }
+      }
+  }
+\cs_new:Npn \__color_model_devicen_mix:nw #1#2 ~ #3 \s__color_mark #4 ~ #5 \s__color_stop
+  {
+    \fp_eval:n { #2 * #1 + #4 * ( 1 - #1 ) }
+    \quark_if_nil:oF { \tl_head:w #3 \q_stop }
+      {
+        \c_space_tl
+        \__color_model_devicen_mix:nw {#1} #3 \s__color_mark #5 \s__color_stop
+      }
+  }
+\cs_new_protected:Npn \__color_model_devicen_init:nnn #1#2#3
+  {
+    \exp_args:Ne \__color_model_devicen_init:nnnn
+      {
+        \str_case:nn {#2}
+          {
+            { cmyk } { 4 }
+            { gray } { 1 }
+            { rgb }  { 3 }
+          }
+      }
+      {#1} {#2} {#3}
+  }
+\cs_new_protected:Npn \__color_model_devicen_init:nnnn #1#2#3#4
+  {
+    \tl_set:Nx \l__color_internal_tl
+      { \prg_replicate:nn {#1} { 1.0 ~ }   }
+    \int_zero:N \l__color_internal_int
+    \clist_map_inline:nn {#4}
+      {
+        \int_incr:N \l__color_internal_int
+        \prop_get:NnN \g__color_alternative_values_prop {##1}
+          \l__color_value_tl
+        \exp_after:wN \__color_model_devicen_transform:w
+          \l__color_value_tl , 0 , 0 , 0 \s__color_stop {#1} {#2}
+      }
+    \tl_put_right:Nx \l__color_internal_tl
+      {
+        \prg_replicate:nn {#1}
+          { neg ~ 1.0 ~ add ~ #1 ~ -1 ~ roll ~ }
+        \int_eval:n { #2 + 4 } ~ 4 ~ roll
+        \prg_replicate:nn {#2} { ~ pop }
+      }
+    \use:x
+      {
+        \__color_backend_devicen_init:nnn
+          {
+            \clist_map_function:nN {#4}
+              \__color_model_devicen_colorant:n
+          }
+          {
+            \str_case:nn {#3}
+              {
+                { cmyk } { /DeviceCMYK }
+                { gray } { /DeviceGray }
+                { rgb }  { /DeviceRGB }
+              }
+          }
+          { \exp_not:V \l__color_internal_tl }
+      }
+  }
+\cs_new_protected:Npn \__color_model_devicen_transform:w
+  #1 , #2 , #3 , #4 , #5 \s__color_stop #6#7
+  {
+    \use:c { __color_model_devicen_transform_ #6 :nnnnn }
+      {#1} {#2} {#3} {#4} {#7}
+  }
+\cs_new_protected:cpn { __color_model_devicen_transform_1:nnnnn } #1#2#3#4#5
+  { \__color_model_devicen_transform:nnn {#5} { 1 } {#1} }
+\cs_new_protected:cpn { __color_model_devicen_transform_3:nnnnn } #1#2#3#4#5
+  {
+    \clist_map_inline { #1 , #2 , #3 }
+      { \__color_model_devicen_transform:nnn {#5} { 3 } {##1} }
+  }
+\cs_new_protected:cpn { __color_model_devicen_transform_4:nnnnn } #1#2#3#4#5
+  {
+    \clist_map_inline:nn { #1 , #2 , #3 , #4 }
+      { \__color_model_devicen_transform:nnn {#5} { 4 } {##1} }
+  }
+\cs_new_protected:Npn \__color_model_devicen_transform:nnn #1#2#3
+  {
+    \tl_put_right:Nx \l__color_internal_tl
+      {
+        \fp_compare:nNnF {#3} = \c_zero_fp
+          {
+            \int_eval:n { #1 - \l__color_internal_int + #2 } ~ index ~
+              #3 ~ neg ~ mul ~ 1.0 ~ add ~ mul ~
+          }
+        #2 ~ -1 ~ roll ~
+      }
+  }
+\cs_new:Npn \__color_model_devicen_colorant:n #1
+  {
+    / \prop_item:Nn \g__color_colorants_prop {#1} ~
+  }
+\cs_new_protected:Npn \__color_model_devicen_convert:nnn #1#2#3
+  {
+    \use:c { __color_model_devicen_convert_ #2 :nn } {#1} {#3}
+  }
+\cs_new_protected:Npn \__color_model_devicen_convert_cmyk:nn #1#2
+  {
+    \__color_model_convert:nnn {#1} { cmyk } { gray }
+    \__color_model_convert:nnn {#1} { cmyk } { rgb }
+    \__color_model_devicen_convert:nnnn {#1} { cmyk } { 4 } {#2}
+  }
+\cs_new_protected:Npn \__color_model_devicen_convert_gray:nn #1#2
+  {
+    \__color_model_convert:nnn {#1} { gray } { cmyk }
+    \__color_model_convert:nnn {#1} { gray } { rgb }
+    \__color_model_devicen_convert:nnnn {#1} { gray } { 1 } {#2}
+  }
+\cs_new_protected:Npn \__color_model_devicen_convert_rgb:nn #1#2
+  {
+    \__color_model_convert:nnn {#1} { rgb } { cmyk }
+    \__color_model_convert:nnn {#1} { rgb } { gray }
+    \__color_model_devicen_convert:nnnn {#1} { rgb } { 3 } {#2}
+  }
+\cs_new_protected:Npn \__color_model_devicen_convert:nnnn #1#2#3#4
+  {
+    \cs_new:cpx { __color_convert_ #1 _ #2 :w } ##1 \s__color_stop
+      {
+        \exp_not:c { __color_convert_devicen_ #2 : \prg_replicate:nn {#3} { n } w }
+          \prg_replicate:nn {#3} { { 1 } }
+          ##1 \exp_not:N \s__color_mark
+          \clist_map_function:nN {#4} \__color_model_devicen_convert:n
+          \exp_not:N \s__color_stop
+      }
+  }
+\cs_new:Npn \__color_model_devicen_convert:n #1
+  {
+    {
+      \exp_args:Ne \__color_model_devicen_convert_aux:n
+        { \prop_item:Nn \g__color_alternative_values_prop {#1} }
+    }
+  }
+\cs_new:Npn \__color_model_devicen_convert_aux:n #1
+  { \__color_model_devicen_convert_aux:w #1 , , , , \s__color_stop }
+\cs_new:Npn \__color_model_devicen_convert_aux:w #1 , #2 , #3 , #4 , #5 \s__color_stop
+  {
+    {#1}
+    \tl_if_blank:nF {#2}
+      {
+        {#2}
+        \tl_if_blank:nF {#3}
+          {
+            {#3}
+            \tl_if_blank:nF {#4} { {#4} }
+          }
+      }
+  }
+\cs_new:Npn \__color_convert_devicen_cmyk:nnnnw
+  #1#2#3#4#5 ~ #6 \s__color_mark #7#8 \s__color_stop
+  {
+    \__color_convert_devicen_cmyk:nnnnnnnnn {#5} {#1} {#2} {#3} {#4} #7
+      #6 \s__color_mark #8 \s__color_stop
+  }
+\cs_new:Npn \__color_convert_devicen_cmyk:nnnnnnnnn #1#2#3#4#5#6#7#8#9
+  {
+    \use:e
+      {
+        \exp_not:N \__color_convert_devicen_cmyk_aux:nnnnw
+          { \fp_eval:n { #2 * (1 - (#1 * #6)) } }
+          { \fp_eval:n { #3 * (1 - (#1 * #7)) } }
+          { \fp_eval:n { #4 * (1 - (#1 * #8)) } }
+          { \fp_eval:n { #5 * (1 - (#1 * #9)) } }
+      }
+  }
+\cs_new:Npn \__color_convert_devicen_cmyk_aux:nnnnw
+  #1#2#3#4 #5 \s__color_mark #6 \s__color_stop
+  {
+    \tl_if_blank:nTF {#5}
+      {
+        \fp_eval:n { 1 - #1 } ~
+        \fp_eval:n { 1 - #2 } ~
+        \fp_eval:n { 1 - #3 } ~
+        \fp_eval:n { 1 - #4 }
+      }
+      {
+        \__color_convert_devicen_cmyk:nnnnw {#1} {#2} {#3} {#4}
+          #5 \s__color_mark #6 \s__color_stop
+      }
+  }
+\cs_new:Npn \__color_convert_devicen_gray:nw
+  #1#2 ~ #3 \s__color_mark #4#5 \s__color_stop
+  {
+    \__color_convert_devicen_gray:nnn {#2} {#1} #4
+      #3 \s__color_mark #5 \s__color_stop
+  }
+\cs_new:Npn \__color_convert_devicen_gray:nnn #1#2#3
+  {
+    \exp_arsgs:Ne \__color_convert_devicen_gray_aux:nw
+      { \fp_eval:n { #2 * (1 - (#1 * #3)) } }
+  }
+\cs_new:Npn \__color_convert_devicen_gray_aux:nw
+  #1 #2 \s__color_mark #3 \s__color_stop
+  {
+    \tl_if_blank:nTF {#2}
+      { \fp_eval:n { 1 - #1 } }
+      {
+        \__color_convert_devicen_gray:nw {#1}
+          #2 \s__color_mark #3 \s__color_stop
+      }
+  }
+\cs_new:Npn \__color_convert_devicen_rgb:nnnw
+  #1#2#3#4 ~ #5 \s__color_mark #6#7 \s__color_stop
+  {
+    \__color_convert_devicen_cmyk:nnnnnn {#4} {#1} {#2} {#3} #6
+      #5 \s__color_mark #7 \s__color_stop
+  }
+\cs_new:Npn \__color_convert_devicen_rgb:nnnnnnn #1#2#3#4#5#6#7
+  {
+    \use:e
+      {
+        \exp_not:N \__color_convert_devicen_rgb_aux:nnnw
+          { \fp_eval:n { #2 * (1 - (#1 * #5)) } }
+          { \fp_eval:n { #3 * (1 - (#1 * #6)) } }
+          { \fp_eval:n { #4 * (1 - (#1 * #7)) } }
+      }
+  }
+\cs_new:Npn \__color_convert_devicen_rgb_aux:nnnw
+  #1#2#3 #4 \s__color_mark #5 \s__color_stop
+  {
+    \tl_if_blank:nTF {#4}
+      {
+        \fp_eval:n { 1 - #1 } ~
+        \fp_eval:n { 1 - #2 } ~
+        \fp_eval:n { 1 - #3 }
+      }
+      {
+        \__color_convert_devicen_rgb:nnnw {#1} {#2} {#3}
+          #4 \s__color_mark #5 \s__color_stop
+      }
+  }
 \cs_new_protected:Npn \color_show:n #1
   {
     \msg_show:nnxxxx { LaTeX / color } { show }
@@ -923,6 +1342,28 @@
     LaTeX~has~been~asked~to~convert~a~color~from~model~'#1'~
     to~model'#2',~but~there~is~no~method~available~to~do~that.
   }
+\__kernel_msg_new:nnnn { color } { DeviceN-inconsistent-alternative }
+  { DeviceN~color~spaces~require~a~single~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
+    but~the~constituent~colors~do~not~have~a~common~alternative~
+    color.
+  }
+\__kernel_msg_new:nnnn { color } { DeviceN-no-alternative }
+  { DeviceN~color~spaces~require~an~alternative~space. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space~'#1',~
+    but~the~constituent~colors~do~not~all~have~a~device-based~alternative.
+  }
+\__kernel_msg_new:nnnn { color } { DeviceN-requires-names }
+  { DeviceN~color~space~'#1'~require~a~list~of~names. }
+  {
+    LaTeX~has~been~asked~to~create~a~DeviceN~color~space,~
+    but~no~\\ \\
+    \iow_indent:n { names~=~<names> }
+    \\ \\
+    key~was~given~with~the~correct~information.
+  }
 \__kernel_msg_new:nnnn { color } { model-already-defined }
   { Color~model~'#1'~already~defined. }
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/l3draw/l3draw.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/l3draw/l3draw.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/l3draw/l3draw.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -28,7 +28,7 @@
 %% 
 %% File: l3draw.dtx
 \RequirePackage{expl3}
-\ProvidesExplPackage{l3draw}{2020-09-11}{}
+\ProvidesExplPackage{l3draw}{2020-09-24}{}
   {L3 Experimental core drawing support}
 \RequirePackage { l3color }
 \scan_new:N \s__draw_mark

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/l3graphics/l3graphics.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/l3graphics/l3graphics.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/l3graphics/l3graphics.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,7 +20,7 @@
 %% 
 %% File: l3graphics.dtx
 \RequirePackage{expl3}
-\ProvidesExplPackage{l3graphics}{2020-09-11}{}
+\ProvidesExplPackage{l3graphics}{2020-09-24}{}
   {L3 Experimental graphics inclusion support}
 \ior_new:N \l__graphics_tmp_ior
 \tl_new:N  \l__graphics_tmp_tl

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/l3pdf/l3pdf.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/l3pdf/l3pdf.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/l3pdf/l3pdf.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,7 +20,7 @@
 %% 
 %% File: l3pdf.dtx
 \RequirePackage{expl3}
-\ProvidesExplPackage{l3pdf}{2020-09-11}{}
+\ProvidesExplPackage{l3pdf}{2020-09-24}{}
   {L3 Experimental core PDF support}
 \scan_new:N \s__pdf_stop
 \bool_new:N \g__pdf_init_bool

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/l3str/l3str-format.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,7 +20,7 @@
 %% 
 %% File: l3str-format.dtx
 \RequirePackage{expl3}
-\ProvidesExplPackage{l3str-format}{2020-09-11}{}
+\ProvidesExplPackage{l3str-format}{2020-09-24}{}
   {L3 Experimental string formatting}
 \cs_generate_variant:Nn \use:nn { nf }
 \cs_generate_variant:Nn \use:nnn { fnf }

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/l3sys-shell/l3sys-shell.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/l3sys-shell/l3sys-shell.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/l3sys-shell/l3sys-shell.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,7 +20,7 @@
 %% 
 %% File: l3sys-shell.dtx
 \RequirePackage{expl3}
-\ProvidesExplPackage{l3sys-shell}{2020-09-11}{}
+\ProvidesExplPackage{l3sys-shell}{2020-09-24}{}
   {L3 Experimental system shell functions}
 \scan_new:N \s__sys_stop
 \quark_new:N \q__sys_nil

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/xcoffins/xcoffins.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,7 +20,7 @@
 %% 
 %% File: xcoffins.dtx
 \RequirePackage{xparse}
-\ProvidesExplPackage{xcoffins}{2020-09-11}{}
+\ProvidesExplPackage{xcoffins}{2020-09-24}{}
   {L3 Experimental design level coffins}
 \keys_define:nn { coffin }
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/l3galley.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -32,7 +32,7 @@
       }%
     \endinput
   }
-\ProvidesExplPackage{l3galley}{2020-09-11}{}
+\ProvidesExplPackage{l3galley}{2020-09-24}{}
   {L3 Experimental galley code}
 \int_new:N \l__galley_tmp_int
 \seq_new:N \g__galley_tmpa_seq

Modified: trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3experimental/xgalley/xgalley.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -20,7 +20,7 @@
 %% 
 %% File: xgalley.dtx
 \RequirePackage{xparse}
-\ProvidesExplPackage{xgalley}{2020-09-11}{}
+\ProvidesExplPackage{xgalley}{2020-09-24}{}
   {L3 Experimental galley}
 \RequirePackage{xparse,xtemplate,l3galley}
 \clist_new:N \l__galley_tmpa_clist

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex	2020-09-24 20:46:14 UTC (rev 56424)
@@ -6,7 +6,7 @@
 %%
 %% expl3.dtx  (with options: `package')
 %% l3bootstrap.dtx  (with options: `package')
-%% l3names.dtx  (with options: `package')
+%% l3names.dtx  (with options: `package,tex')
 %% l3basics.dtx  (with options: `package')
 %% l3expan.dtx  (with options: `package')
 %% l3quark.dtx  (with options: `package')
@@ -16,9 +16,9 @@
 %% l3int.dtx  (with options: `package')
 %% l3flag.dtx  (with options: `package')
 %% l3prg.dtx  (with options: `package')
-%% l3sys.dtx  (with options: `package')
+%% l3sys.dtx  (with options: `package,tex')
 %% l3clist.dtx  (with options: `package')
-%% l3token.dtx  (with options: `package')
+%% l3token.dtx  (with options: `package,tex')
 %% l3prop.dtx  (with options: `package')
 %% l3msg.dtx  (with options: `package')
 %% l3file.dtx  (with options: `package')
@@ -69,7 +69,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-09-06}%
+\def\ExplFileDate{2020-09-24}%
 \begingroup
   \def\next{\endgroup}%
   \expandafter\ifx\csname PackageError\endcsname\relax
@@ -151,12 +151,16 @@
 \begingroup\expandafter\expandafter\expandafter\endgroup
 \expandafter\ifx\csname directlua\endcsname\relax
 \else
-  \ifnum\luatexversion<95 %
+  \ifnum\luatexversion<110 %
   \else
     \begingroup\expandafter\expandafter\expandafter\endgroup
     \expandafter\ifx\csname newcatcodetable\endcsname\relax
       \input{ltluatex}%
     \fi
+    \begingroup\edef\ignored{%
+      \expandafter\noexpand\csname prg_return_true:\endcsname
+      \expandafter\noexpand\csname prg_return_false:\endcsname
+    }\endgroup
     \directlua{require("expl3")}%
     \ifnum 0%
       \directlua{
@@ -182,7 +186,7 @@
       These are available in the engines\LineBreak
       - pdfTeX v1.40\LineBreak
       - XeTeX v0.99992\LineBreak
-      - LuaTeX v0.95\LineBreak
+      - LuaTeX v1.10\LineBreak
       - e-(u)pTeX mid-2012\LineBreak
       or later.\LineBreak
       \LineBreak
@@ -205,7 +209,7 @@
     \fi
     \expandafter\ifx\csname directlua\endcsname\relax
     \else
-      \ifnum\luatexversion<76 \else 1\fi
+      \ifnum\luatexversion<110 \else 1\fi
     \fi
     =0 %
       \newlinechar`\^^J %
@@ -775,9 +779,6 @@
   \__kernel_primitive:NN \pdfeachlinedepth      \tex_eachlinedepth:D
   \__kernel_primitive:NN \pdfeachlineheight     \tex_eachlineheight:D
   \__kernel_primitive:NN \pdfelapsedtime        \tex_elapsedtime:D
-  \__kernel_primitive:NN \pdffiledump           \tex_filedump:D
-  \__kernel_primitive:NN \pdffilemoddate        \tex_filemoddate:D
-  \__kernel_primitive:NN \pdffilesize           \tex_filesize:D
   \__kernel_primitive:NN \pdffirstlineheight    \tex_firstlineheight:D
   \__kernel_primitive:NN \pdffontexpand         \tex_fontexpand:D
   \__kernel_primitive:NN \pdffontsize           \tex_fontsize:D
@@ -788,7 +789,6 @@
   \__kernel_primitive:NN \pdflastypos           \tex_lastypos:D
   \__kernel_primitive:NN \pdfmapfile            \tex_mapfile:D
   \__kernel_primitive:NN \pdfmapline            \tex_mapline:D
-  \__kernel_primitive:NN \pdfmdfivesum          \tex_mdfivesum:D
   \__kernel_primitive:NN \pdfnoligatures        \tex_noligatures:D
   \__kernel_primitive:NN \pdfnormaldeviate      \tex_normaldeviate:D
   \__kernel_primitive:NN \pdfpageheight         \tex_pageheight:D
@@ -801,7 +801,6 @@
   \__kernel_primitive:NN \pdfrandomseed         \tex_randomseed:D
   \__kernel_primitive:NN \pdfresettimer         \tex_resettimer:D
   \__kernel_primitive:NN \pdfsavepos            \tex_savepos:D
-  \__kernel_primitive:NN \pdfstrcmp             \tex_strcmp:D
   \__kernel_primitive:NN \pdfsetrandomseed      \tex_setrandomseed:D
   \__kernel_primitive:NN \pdfshellescape        \tex_shellescape:D
   \__kernel_primitive:NN \pdftracingfonts       \tex_tracingfonts:D
@@ -828,6 +827,11 @@
       \tex_fi:D
         \use_none:n { \tex_global:D \tex_let:D #2 #1 }
     }
+  \__kernel_primitive:NN \pdfstrcmp             \tex_strcmp:D
+  \__kernel_primitive:NN \pdffilesize           \tex_filesize:D
+  \__kernel_primitive:NN \pdfmdfivesum          \tex_mdfivesum:D
+  \__kernel_primitive:NN \pdffilemoddate        \tex_filemoddate:D
+  \__kernel_primitive:NN \pdffiledump           \tex_filedump:D
   \__kernel_primitive:NN \suppressfontnotfounderror
     \tex_suppressfontnotfounderror:D
   \__kernel_primitive:NN \XeTeXcharclass        \tex_XeTeXcharclass:D
@@ -4772,28 +4776,7 @@
   { p , T , F , TF }
 \prg_new_eq_conditional:NNn \str_if_empty:c \tl_if_empty:c
   { p , T , F , TF }
-\cs_new:Npn \__str_if_eq:nn #1#2 { \tex_strcmp:D {#1} {#2} }
-\cs_if_exist:NT \tex_luatexversion:D
-   {
-     \cs_set_eq:NN \lua_escape:e \tex_luaescapestring:D
-     \cs_set_eq:NN \lua_now:e    \tex_directlua:D
-     \cs_set:Npn \__str_if_eq:nn #1#2
-       {
-          \lua_now:e
-            {
-              l3kernel.strcmp
-                (
-                  " \__str_escape:n {#1} " ,
-                  " \__str_escape:n {#2} "
-                )
-            }
-       }
-     \cs_new:Npn \__str_escape:n #1
-       {
-         \lua_escape:e
-           { \__kernel_tl_to_str:w \use:e { {#1} } }
-       }
-   }
+\cs_new_eq:NN \__str_if_eq:nn \tex_strcmp:D
 \prg_new_conditional:Npnn \str_if_eq:nn #1#2 { p , T , F , TF }
   {
     \if_int_compare:w
@@ -7173,23 +7156,26 @@
     \__sys_const:nn { sys_if_engine_ #1 }
       { \str_if_eq_p:Vn \c_sys_engine_str {#1} }
   }
-\str_const:Nx \c_sys_engine_exec_str
-  {
-    \sys_if_engine_pdftex:T { pdf }
-    \sys_if_engine_xetex:T  { xe  }
-    \sys_if_engine_ptex:T   { ep  }
-    \sys_if_engine_uptex:T  { eup }
-    \sys_if_engine_luatex:T
-      {
-        lua \lua_now:e
-          {
-            if (pcall(require, 'luaharfbuzz')) then ~
-              tex.print("hb") ~
-            end
-          }
-      }
-    tex
-  }
+\group_begin:
+  \cs_set_eq:NN \lua_now:e    \tex_directlua:D
+  \str_const:Nx \c_sys_engine_exec_str
+    {
+      \sys_if_engine_pdftex:T { pdf }
+      \sys_if_engine_xetex:T  { xe  }
+      \sys_if_engine_ptex:T   { ep  }
+      \sys_if_engine_uptex:T  { eup }
+      \sys_if_engine_luatex:T
+        {
+          lua \lua_now:e
+            {
+              if (pcall(require, 'luaharfbuzz')) then ~
+                tex.print("hb") ~
+              end
+            }
+        }
+      tex
+    }
+\group_end:
 \str_const:Nx \c_sys_engine_format_str
   {
     \cs_if_exist:NTF \fmtname
@@ -7355,10 +7341,7 @@
 \sys_if_engine_luatex:TF
   {
     \cs_new_protected:Npn \sys_shell_now:n #1
-      {
-        \lua_now:e
-          { l3kernel.shellescape(" \lua_escape:e { \tl_to_str:n {#1} } ") }
-      }
+      { \__sys_shell_now:e { \exp_not:n {#1} } }
   }
   {
     \cs_new_protected:Npn \sys_shell_now:n #1
@@ -7368,10 +7351,7 @@
 \sys_if_engine_luatex:TF
   {
     \cs_new_protected:Npn \sys_shell_shipout:n #1
-      {
-        \lua_shipout_e:n
-          { l3kernel.shellescape(" \lua_escape:e { \tl_to_str:n {#1} } ") }
-      }
+    { \__sys_shell_shipout:e { \exp_not:n {#1} } }
   }
   {
     \cs_new_protected:Npn \sys_shell_shipout:n #1
@@ -8300,37 +8280,26 @@
   \if_int_odd:w 0
       \sys_if_engine_luatex:T { 1 }
       \sys_if_engine_xetex:T { 1 } \exp_stop_f:
-    \sys_if_engine_luatex:TF
-      {
-        \cs_new:Npn \__char_generate_aux:nnw #1#2#3 \exp_end:
-          {
-            #3
-            \exp_after:wN \exp_after:wN \exp_after:wN \exp_end:
-            \lua_now:e { l3kernel.charcat(#1, #2) }
-          }
-      }
-      {
-        \cs_new:Npn \__char_generate_aux:nnw #1#2#3 \exp_end:
-          {
-            #3
-            \exp_after:wN \exp_end:
-            \tex_Ucharcat:D #1 \exp_stop_f: #2 \exp_stop_f:
-          }
-        \cs_if_exist:NF \tex_expanded:D
-          {
-            \cs_new_eq:NN \__char_generate_auxii:nnw \__char_generate_aux:nnw
-            \cs_gset:Npn \__char_generate_aux:nnw #1#2#3 \exp_end:
-              {
-                #3
-                \if_int_compare:w #2 = 13 \exp_stop_f:
-                  \__kernel_msg_expandable_error:nn { kernel } { char-active }
-                \else:
-                  \__char_generate_auxii:nnw {#1} {#2}
-                \fi:
-                \exp_end:
-              }
-          }
-      }
+      \cs_new:Npn \__char_generate_aux:nnw #1#2#3 \exp_end:
+        {
+          #3
+          \exp_after:wN \exp_end:
+          \tex_Ucharcat:D #1 \exp_stop_f: #2 \exp_stop_f:
+        }
+      \cs_if_exist:NF \tex_expanded:D
+        {
+          \cs_new_eq:NN \__char_generate_auxii:nnw \__char_generate_aux:nnw
+          \cs_gset:Npn \__char_generate_aux:nnw #1#2#3 \exp_end:
+            {
+              #3
+              \if_int_compare:w #2 = 13 \exp_stop_f:
+                \__kernel_msg_expandable_error:nn { kernel } { char-active }
+              \else:
+                \__char_generate_auxii:nnw {#1} {#2}
+              \fi:
+              \exp_end:
+            }
+        }
   \else:
       \tl_set:Nn \l__char_tmp_tl { \exp_not:N \or: }
       \char_set_catcode_group_begin:n { 0 } % {
@@ -8809,67 +8778,76 @@
 \__token_tmp:w { skip_register } { skip } { \token_to_str:N \skip }
 \__token_tmp:w { toks_register } { toks } { \token_to_str:N \toks }
 \group_end:
-\tex_chardef:D \c__token_A_int = `A ~ %
-\use:x
+\sys_if_engine_luatex:TF
   {
-    \prg_new_conditional:Npnn \exp_not:N \token_if_primitive:N ##1
-      { p , T , F , TF }
+    \prg_new_conditional:Npnn \token_if_primitive:N #1 { p , T , F , TF }
       {
-        \exp_not:N \token_if_macro:NTF ##1
-          \exp_not:N \prg_return_false:
-          {
-            \exp_not:N \exp_after:wN \exp_not:N \__token_if_primitive:NNw
-            \exp_not:N \token_to_meaning:N ##1
-              \tl_to_str:n { : : : } \s__token_stop ##1
-          }
+        \__token_if_primitive_lua:N #1
       }
-    \cs_new:Npn \exp_not:N \__token_if_primitive:NNw
-      ##1##2 ##3 \c_colon_str ##4 \s__token_stop
+  }
+  {
+    \tex_chardef:D \c__token_A_int = `A ~ %
+    \use:x
       {
-        \exp_not:N \tl_if_empty:oTF
-          { \exp_not:N \__token_if_primitive_space:w ##3 ~ }
+        \prg_new_conditional:Npnn \exp_not:N \token_if_primitive:N ##1
+          { p , T , F , TF }
           {
-            \exp_not:N \__token_if_primitive_loop:N ##3
-              \c_colon_str \s__token_stop
+            \exp_not:N \token_if_macro:NTF ##1
+              \exp_not:N \prg_return_false:
+              {
+                \exp_not:N \exp_after:wN \exp_not:N \__token_if_primitive:NNw
+                \exp_not:N \token_to_meaning:N ##1
+                  \tl_to_str:n { : : : } \s__token_stop ##1
+              }
           }
-          { \exp_not:N \__token_if_primitive_nullfont:N }
+        \cs_new:Npn \exp_not:N \__token_if_primitive:NNw
+          ##1##2 ##3 \c_colon_str ##4 \s__token_stop
+          {
+            \exp_not:N \tl_if_empty:oTF
+              { \exp_not:N \__token_if_primitive_space:w ##3 ~ }
+              {
+                \exp_not:N \__token_if_primitive_loop:N ##3
+                  \c_colon_str \s__token_stop
+              }
+              { \exp_not:N \__token_if_primitive_nullfont:N }
+          }
       }
+    \cs_new:Npn \__token_if_primitive_space:w #1 ~ { }
+    \cs_new:Npn \__token_if_primitive_nullfont:N #1
+      {
+        \if_meaning:w \tex_nullfont:D #1
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
+    \cs_new:Npn \__token_if_primitive_loop:N #1
+      {
+        \if_int_compare:w `#1 < \c__token_A_int %
+          \exp_after:wN \__token_if_primitive:Nw
+          \exp_after:wN #1
+        \else:
+          \exp_after:wN \__token_if_primitive_loop:N
+        \fi:
+      }
+    \cs_new:Npn \__token_if_primitive:Nw #1 #2 \s__token_stop
+      {
+        \if:w : #1
+          \exp_after:wN \__token_if_primitive_undefined:N
+        \else:
+          \prg_return_false:
+          \exp_after:wN \use_none:n
+        \fi:
+      }
+    \cs_new:Npn \__token_if_primitive_undefined:N #1
+      {
+        \if_cs_exist:N #1
+          \prg_return_true:
+        \else:
+          \prg_return_false:
+        \fi:
+      }
   }
-\cs_new:Npn \__token_if_primitive_space:w #1 ~ { }
-\cs_new:Npn \__token_if_primitive_nullfont:N #1
-  {
-    \if_meaning:w \tex_nullfont:D #1
-      \prg_return_true:
-    \else:
-      \prg_return_false:
-    \fi:
-  }
-\cs_new:Npn \__token_if_primitive_loop:N #1
-  {
-    \if_int_compare:w `#1 < \c__token_A_int %
-      \exp_after:wN \__token_if_primitive:Nw
-      \exp_after:wN #1
-    \else:
-      \exp_after:wN \__token_if_primitive_loop:N
-    \fi:
-  }
-\cs_new:Npn \__token_if_primitive:Nw #1 #2 \s__token_stop
-  {
-    \if:w : #1
-      \exp_after:wN \__token_if_primitive_undefined:N
-    \else:
-      \prg_return_false:
-      \exp_after:wN \use_none:n
-    \fi:
-  }
-\cs_new:Npn \__token_if_primitive_undefined:N #1
-  {
-    \if_cs_exist:N #1
-      \prg_return_true:
-    \else:
-      \prg_return_false:
-    \fi:
-  }
 \cs_new_eq:NN \l_peek_token ?
 \cs_new_eq:NN \g_peek_token ?
 \cs_new_eq:NN \l__peek_search_token ?
@@ -11198,14 +11176,6 @@
     \tl_set:No #1 {#2}
   }
 \cs_new_eq:NN \__file_size:n \tex_filesize:D
-\sys_if_engine_luatex:T
-  {
-    \cs_gset:Npn \__file_size:n #1
-      {
-        \lua_now:e
-          { l3kernel.filesize ( " \lua_escape:e {#1} " ) }
-      }
-  }
 \cs_new:Npn \file_full_name:n #1
   {
     \exp_args:Ne \__file_full_name:n
@@ -11275,9 +11245,7 @@
           {#1}
       }
   }
-\bool_lazy_or:nnF
-  { \cs_if_exist_p:N \tex_filesize:D }
-  { \sys_if_engine_luatex_p: }
+\cs_if_exist:NF \tex_filesize:D
   {
     \cs_gset:Npn \file_full_name:n #1
       {
@@ -11309,9 +11277,7 @@
 \cs_generate_variant:Nn \file_get_full_name:nNT  { V }
 \cs_generate_variant:Nn \file_get_full_name:nNF  { V }
 \cs_generate_variant:Nn \file_get_full_name:nNTF { V }
-\bool_lazy_or:nnF
-  { \cs_if_exist_p:N \tex_filesize:D }
-  { \sys_if_engine_luatex_p: }
+\cs_if_exist:NF \tex_filesize:D
   {
     \prg_set_protected_conditional:Npnn \file_get_full_name:nN #1#2 { T , F , TF }
       {
@@ -11356,8 +11322,6 @@
     \ior_if_eof:NF \g__file_internal_ior { #2 { \prg_break: } }
   }
 \ior_new:N \g__file_internal_ior
-\cs_new:Npn \file_mdfive_hash:n #1
-  { \__file_details:nn {#1} { mdfivesum } }
 \cs_new:Npn \file_size:n #1
   { \__file_details:nn {#1} { size } }
 \cs_new:Npn \file_timestamp:n #1
@@ -11372,20 +11336,10 @@
     \tl_if_blank:nF {#1}
       { \use:c { tex_file #2 :D } {#1} }
   }
-\sys_if_engine_luatex:TF
-  {
-    \cs_gset:Npn \__file_details_aux:nn #1#2
-      {
-        \lua_now:e
-          { l3kernel.file#2 ( " \lua_escape:e { #1 } " ) }
-      }
-  }
-  {
-    \cs_gset:Npn \file_mdfive_hash:n #1
-      { \exp_args:Ne \__file_mdfive_hash:n { \file_full_name:n {#1} } }
-    \cs_new:Npn \__file_mdfive_hash:n #1
-      { \tex_mdfivesum:D file {#1} }
-  }
+\cs_new:Npn \file_mdfive_hash:n #1
+  { \exp_args:Ne \__file_mdfive_hash:n { \file_full_name:n {#1} } }
+\cs_new:Npn \__file_mdfive_hash:n #1
+  { \tex_mdfivesum:D file {#1} }
 \cs_new:Npn \file_hex_dump:nnn #1#2#3
   {
     \exp_args:Neee \__file_hex_dump_auxi:nnn
@@ -11434,34 +11388,21 @@
       length ~ \int_eval:n { #1 - #2 + 1 }
       {#3}
   }
-\sys_if_engine_luatex:T
+\cs_new:Npn \file_hex_dump:n #1
+  { \exp_args:Ne \__file_hex_dump:n { \file_full_name:n {#1} } }
+\sys_if_engine_luatex:TF
   {
-    \cs_gset:Npn \__file_hex_dump_auxiv:nnn #1#2#3
+    \cs_new:Npn \__file_hex_dump:n #1
       {
-        \lua_now:e
-          {
-            l3kernel.filedump
-              (
-                " \lua_escape:e {#3} " ,
-                \int_eval:n { #2 - 1 } ,
-                \int_eval:n { #1 - #2 + 1 }
-              )
-          }
+        \tl_if_blank:nF {#1}
+          { \tex_filedump:D whole {#1} {#1} }
       }
   }
-\cs_new:Npn \file_hex_dump:n #1
-  { \exp_args:Ne \__file_hex_dump:n { \file_full_name:n {#1} } }
-\cs_new:Npn \__file_hex_dump:n #1
   {
-    \tl_if_blank:nF {#1}
-      { \tex_filedump:D length \tex_filesize:D {#1} {#1} }
-  }
-\sys_if_engine_luatex:T
-  {
-    \cs_gset:Npn \__file_hex_dump:n #1
+    \cs_new:Npn \__file_hex_dump:n #1
       {
-        \lua_now:e
-          { l3kernel.filedump ( " \lua_escape:e { #1 } " ) }
+        \tl_if_blank:nF {#1}
+          { \tex_filedump:D length \tex_filesize:D {#1} {#1} }
       }
   }
 \cs_new_protected:Npn \file_get_hex_dump:nN #1#2
@@ -11488,9 +11429,7 @@
       { \prg_return_false: }
       { \prg_return_true: }
   }
-\bool_lazy_or:nnF
-  { \cs_if_exist_p:N \tex_filesize:D }
-  { \sys_if_engine_luatex_p: }
+\cs_if_exist:NF \tex_filesize:D
   {
     \cs_set_protected:Npn \__file_get_details:nnN #1#2#3
        {
@@ -11524,26 +11463,7 @@
       { \prg_return_false: }
       { \prg_return_true: }
   }
-\cs_new:Npn \__file_str_cmp:nn #1#2 { \tex_strcmp:D {#1} {#2} }
-\sys_if_engine_luatex:T
-  {
-    \cs_set:Npn \__file_str_cmp:nn #1#2
-      {
-        \lua_now:e
-          {
-            l3kernel.strcmp
-              (
-                " \__file_str_escape:n {#1}",
-                " \__file_str_escape:n {#2}"
-              )
-          }
-      }
-   \cs_new:Npn \__file_str_escape:n #1
-     {
-       \lua_escape:e
-         { \__kernel_tl_to_str:w \use:e { {#1} } }
-     }
-  }
+\cs_new_eq:NN \__file_str_cmp:nn \tex_strcmp:D
 \prg_new_conditional:Npnn \file_compare_timestamp:nNn #1#2#3
   { p , T , F , TF }
   {
@@ -11584,15 +11504,7 @@
           }
       }
   }
-\sys_if_engine_luatex:TF
-  {
-    \cs_new:Npn \__file_timestamp:n #1
-      {
-        \lua_now:e
-          { l3kernel.filemoddate ( " \lua_escape:e {#1} " ) }
-      }
-  }
-  { \cs_new_eq:NN \__file_timestamp:n \tex_filemoddate:D }
+\cs_new_eq:NN \__file_timestamp:n \tex_filemoddate:D
 \cs_if_exist:NF \__file_timestamp:n
   {
     \prg_set_conditional:Npnn \file_compare_timestamp:nNn #1#2#3
@@ -14272,21 +14184,7 @@
       \exp_after:wN \use_ii:nn
     \fi:
   }
-\sys_if_engine_luatex:TF
-  {
-    \cs_new:Npn \__fp_str_if_eq:nn #1#2
-      {
-        \tex_directlua:D
-          {
-            l3kernel.strcmp
-              (
-                " \tex_luaescapestring:D {#1}",
-                " \tex_luaescapestring:D {#2}"
-              )
-          }
-      }
-  }
-  { \cs_new_eq:NN \__fp_str_if_eq:nn \tex_strcmp:D }
+\cs_new_eq:NN \__fp_str_if_eq:nn \tex_strcmp:D
 \cs_new:Npn \__fp_func_to_name:N #1
   {
     \exp_last_unbraced:Nf
@@ -28008,22 +27906,9 @@
         {
           \exp_not:N \tex_unexpanded:D \exp_not:N \exp_after:wN
             {
-              \sys_if_engine_luatex:TF
-                {
-                  \exp_not:N \tex_directlua:D
-                    {
-                      l3kernel.charcat
-                        (
-                          \exp_not:N \tex_number:D #1 ,
-                          \exp_not:N \tex_the:D \tex_catcode:D #1
-                        )
-                    }
-                }
-                {
-                  \exp_not:N \tex_Ucharcat:D
-                    #1 ~
-                    \tex_catcode:D #1 ~
-                }
+              \exp_not:N \tex_Ucharcat:D
+                #1 ~
+                \tex_catcode:D #1 ~
             }
         }
       \ior_open:Nn \g__char_data_ior { UnicodeData.txt }

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex	2020-09-24 20:46:14 UTC (rev 56424)
@@ -19,7 +19,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-09-06}%
+\def\ExplFileDate{2020-09-24}%
 \let\ExplLoaderFileDate\ExplFileDate
 \begingroup
   \catcode`\>=12

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx	2020-09-24 20:46:14 UTC (rev 56424)
@@ -19,7 +19,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-09-06}%
+\def\ExplFileDate{2020-09-24}%
 \let\ExplLoaderFileDate\ExplFileDate
 \begingroup
   \catcode`\>=12

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.lua	2020-09-24 20:46:14 UTC (rev 56424)
@@ -5,6 +5,9 @@
 -- The original source files were:
 --
 -- l3luatex.dtx  (with options: `package,lua')
+-- l3names.dtx  (with options: `package,lua')
+-- l3sys.dtx  (with options: `package,lua')
+-- l3token.dtx  (with options: `package,lua')
 -- 
 -- Copyright (C) 1990-2020 The LaTeX3 Project
 -- 
@@ -20,6 +23,10 @@
 -- 
 -- File: l3luatex.dtx
 l3kernel = l3kernel or { }
+local l3kernel = l3kernel
+ltx = ltx or {utils={}}
+ltx.utils = ltx.utils or { }
+local ltxutils = ltx.utils
 local io       = io
 local kpse     = kpse
 local lfs      = lfs
@@ -30,7 +37,6 @@
 local tex      = tex
 local texio    = texio
 local tonumber = tonumber
-local unicode  = unicode
 local abs        = math.abs
 local byte       = string.byte
 local floor      = math.floor
@@ -37,30 +43,41 @@
 local format     = string.format
 local gsub       = string.gsub
 local lfs_attr   = lfs.attributes
-local md5_sum    = md5.sum
 local open       = io.open
-local os_clock   = os.clock
 local os_date    = os.date
-local os_exec    = os.execute
 local setcatcode = tex.setcatcode
 local sprint     = tex.sprint
 local cprint     = tex.cprint
 local write      = tex.write
 local write_nl   = texio.write_nl
-local utf8_char = (utf8 and utf8.char) or (utf and utf.char) or unicode.utf8.char
+local utf8_char  = utf8.char
+
+local scan_int     = token.scan_int or token.scan_integer
+local scan_string  = token.scan_string
+local scan_keyword = token.scan_keyword
+local put_next     = token.put_next
+
+local true_tok     = token.create'prg_return_true:'
+local false_tok    = token.create'prg_return_false:'
+local function deprecated(table, name, func)
+  table[name] = function(...)
+    write_nl(format("Calling deprecated Lua function %s", name))
+    table[name] = func
+    return func(...)
+  end
+end
 local kpse_find = (resolvers and resolvers.findfile) or kpse.find_file
 local function escapehex(str)
-  write((gsub(str, ".",
-    function (ch) return format("%02X", byte(ch)) end)))
+  return (gsub(str, ".",
+    function (ch) return format("%02X", byte(ch)) end))
 end
-local charcat
-function charcat(charcode, catcode)
+deprecated(l3kernel, 'charcat', function(charcode, catcode)
   cprint(catcode, utf8_char(charcode))
-end
-l3kernel.charcat = charcat
-local base_time = 0
+end)
+local os_clock   = os.clock
+local base_clock_time = 0
 local function elapsedtime()
-  local val = (os_clock() - base_time) * 65536 + 0.5
+  local val = (os_clock() - base_clock_time) * 65536 + 0.5
   if val > 2147483647 then
     val = 2147483647
   end
@@ -68,94 +85,127 @@
 end
 l3kernel.elapsedtime = elapsedtime
 local function resettimer()
-  base_time = os_clock()
+  base_clock_time = os_clock()
 end
 l3kernel.resettimer = resettimer
 local function filedump(name,offset,length)
   local file = kpse_find(name,"tex",true)
-  if file then
-    local length = tonumber(length) or lfs_attr(file,"size")
-    local offset = tonumber(offset) or 0
-    local f = open(file,"rb")
-    if f then
-      if offset > 0 then
-        f:seek("set",offset)
-      end
-      local data = f:read(length)
-      escapehex(data)
-      f:close()
-    end
+  if not file then return end
+  local f = open(file,"rb")
+  if not f then return end
+  if offset and offset > 0 then
+    f:seek("set", offset)
   end
+  local data = f:read(length or 'a')
+  f:close()
+  return escapehex(data)
 end
-l3kernel.filedump = filedump
-local function filemdfivesum(name)
-  local file =  kpse_find(name, "tex", true)
-  if file then
-    local f = open(file, "rb")
-    if f then
-      local data = f:read("*a")
-      escapehex(md5_sum(data))
-      f:close()
-    end
+ltxutils.filedump = filedump
+deprecated(l3kernel, "filedump", function(name, offset, length)
+  local dump = filedump(name, tonumber(offset), tonumber(length))
+  if dump then
+    write(dump)
   end
+end)
+local md5_HEX = md5.HEX
+if not md5_HEX then
+  local md5_sum = md5.sum
+  function md5_HEX(data)
+    return escapehex(md5_sum(data))
+  end
+  md5.HEX = md5_HEX
 end
-l3kernel.filemdfivesum = filemdfivesum
-local function filemoddate(name)
-  local file =  kpse_find(name, "tex", true)
-  if file then
+local function filemd5sum(name)
+  local file = kpse_find(name, "tex", true) if not file then return end
+  local f = open(file, "rb") if not f then return end
+
+  local data = f:read("*a")
+  f:close()
+  return md5_HEX(data)
+end
+ltxutils.filemd5sum = filemd5sum
+deprecated(l3kernel, "filemdfivesum", function(name)
+  local hash = filemd5sum(name)
+  if hash then
+    write(hash)
+  end
+end)
+local filemoddate
+if os_date'%z':match'^[+-]%d%d%d%d$' then
+  local pattern = lpeg.Cs(16 *
+      (lpeg.Cg(lpeg.S'+-' * '0000' * lpeg.Cc'Z')
+    + 3 * lpeg.Cc"'" * 2 * lpeg.Cc"'"
+    + lpeg.Cc'Z')
+  * -1)
+  function filemoddate(name)
+    local file = kpse_find(name, "tex", true)
+    if not file then return end
     local date = lfs_attr(file, "modification")
-    if date then
-      local d = os_date("*t", date)
-      if d.sec >= 60 then
-        d.sec = 59
+    if not date then return end
+    return pattern:match(os_date("D:%Y%m%d%H%M%S%z", date))
+  end
+else
+  local function filemoddate(name)
+    local file = kpse_find(name, "tex", true)
+    if not file then return end
+    local date = lfs_attr(file, "modification")
+    if not date then return end
+    local d = os_date("*t", date)
+    local u = os_date("!*t", date)
+    local off = 60 * (d.hour - u.hour) + d.min - u.min
+    if d.year ~= u.year then
+      if d.year > u.year then
+        off = off + 1440
+      else
+        off = off - 1440
       end
-      local u = os_date("!*t", date)
-      local off = 60 * (d.hour - u.hour) + d.min - u.min
-      if d.year ~= u.year then
-        if d.year > u.year then
-          off = off + 1440
-        else
-          off = off - 1440
-        end
-      elseif d.yday ~= u.yday then
-        if d.yday > u.yday then
-          off = off + 1440
-        else
-          off = off - 1440
-        end
+    elseif d.yday ~= u.yday then
+      if d.yday > u.yday then
+        off = off + 1440
+      else
+        off = off - 1440
       end
-      local timezone
-      if off == 0 then
-        timezone = "Z"
+    end
+    local timezone
+    if off == 0 then
+      timezone = "Z"
+    else
+      if off < 0 then
+        timezone = "-"
+        off = -off
       else
-        local hours = floor(off / 60)
-        local mins  = abs(off - hours * 60)
-        timezone = format("%+03d", hours)
-          .. "'" .. format("%02d", mins) .. "'"
+        timezone = "+"
       end
-      write("D:"
-        .. format("%04d", d.year)
-        .. format("%02d", d.month)
-        .. format("%02d", d.day)
-        .. format("%02d", d.hour)
-        .. format("%02d", d.min)
-        .. format("%02d", d.sec)
-        .. timezone)
+      timezone = format("%s%02d'%02d'", timezone, hours // 60, hours % 60)
     end
+    return format("D:%04d%02d%02d%02d%02d%02d%s",
+        d.year, d.month, d.day, d.hour, d.min, d.sec, timezone)
   end
 end
-l3kernel.filemoddate = filemoddate
+ltxutils.filemoddate = filemoddate
+deprecated(l3kernel, "filemoddate", function(name)
+  local hash = filemoddate(name)
+  if hash then
+    write(hash)
+  end
+end)
 local function filesize(name)
-  local file =  kpse_find(name, "tex", true)
+  local file = kpse_find(name, "tex", true)
   if file then
     local size = lfs_attr(file, "size")
     if size then
-      write(size)
+      return size
     end
   end
 end
-l3kernel.filesize = filesize
-local function strcmp(A, B)
+ltxutils.filesize = filesize
+deprecated(l3kernel, "filesize", function(name)
+  local size = filesize(name)
+  if size then
+    write(size)
+  end
+end)
+deprecated(l3kernel, "strcmp", function (A, B)
   if A == B then
     write("0")
   elseif A < B then
@@ -163,9 +213,9 @@
   else
     write("1")
   end
-end
-l3kernel.strcmp = strcmp
-local function shellescape(cmd)
+end)
+local os_exec    = os.execute
+deprecated(l3kernel, "shellescape", function(cmd)
   local status,msg = os_exec(cmd)
   if status == nil then
     write_nl("log","runsystem(" .. cmd .. ")...(" .. msg .. ")\n")
@@ -174,5 +224,163 @@
   else
     write_nl("log","runsystem(" .. cmd .. ")...failed " .. (msg or "") .. "\n")
   end
+end)
+local luacmd do
+  local token_create = token.create
+  local set_lua = token.set_lua
+  local undefined_cs = token.command_id'undefined_cs'
+
+  if not context and not luatexbase then require'ltluatex' end
+  if luatexbase then
+    local new_luafunction = luatexbase.new_luafunction
+    local functions = lua.get_functions_table()
+    function luacmd(name, func, ...)
+      local id
+      local tok = token_create(name)
+      if tok.command == undefined_cs then
+        id = new_luafunction(name)
+        set_lua(name, id, ...)
+      else
+        id = tok.index or tok.mode
+      end
+      functions[id] = func
+    end
+  elseif context then
+    local register = context.functions.register
+    local functions = context.functions.known
+    function luacmd(name, func, ...)
+      local tok = token.create(name)
+      if tok.command == undefined_cs then
+        token.set_lua(name, register(func), ...)
+      else
+        functions[tok.index or tok.mode] = func
+      end
+    end
+  end
 end
-l3kernel.shellescape = shellescape
+-- File: l3names.dtx
+luacmd('tex_strcmp:D', function()
+  local first = scan_string()
+  local second = scan_string()
+  write(first == second and '0'
+     or first < second and '-1'
+     or '1')
+end, 'global')
+local cprint = tex.cprint
+luacmd('tex_Ucharcat:D', function()
+  local charcode = scan_int()
+  local catcode = scan_int()
+  cprint(catcode, utf8_char(charcode))
+end, 'global')
+luacmd('tex_filesize:D', function()
+  local size = filesize(scan_string())
+  if size then write(size) end
+end, 'global')
+luacmd('tex_mdfivesum:D', function()
+  local hash
+  if scan_keyword"file" then
+    hash = filemd5sum(scan_string())
+  else
+    hash = md5_HEX(scan_string())
+  end
+  if hash then write(hash) end
+end, 'global')
+luacmd('tex_filemoddate:D', function()
+  local date = filemoddate(scan_string())
+  if date then write(date) end
+end, 'global')
+luacmd('tex_filedump:D', function()
+  local offset = scan_keyword'offset' and scan_int() or nil
+  local length = scan_keyword'length' and scan_int()
+          or not scan_keyword'whole' and 0 or nil
+  local data = filedump(scan_string(), offset, length)
+  if data then write(data) end
+end, 'global')
+-- File: l3sys.dtx
+do
+  local os_exec = os.execute
+
+  local function shellescape(cmd)
+    local status,msg = os_exec(cmd)
+    if status == nil then
+      write_nl("log","runsystem(" .. cmd .. ")...(" .. msg .. ")\n")
+    elseif status == 0 then
+      write_nl("log","runsystem(" .. cmd .. ")...executed\n")
+    else
+      write_nl("log","runsystem(" .. cmd .. ")...failed " .. (msg or "") .. "\n")
+    end
+  end
+  luacmd("__sys_shell_now:e", function()
+    shellescape(scan_string())
+  end, "global", "protected")
+  local whatsit_id = node.id'whatsit'
+  local latelua_sub = node.subtype'late_lua'
+  local node_new = node.direct.new
+  local setfield = node.direct.setwhatsitfield or node.direct.setfield
+  local node_write = node.direct.write
+
+  luacmd("__sys_shell_shipout:e", function()
+    local cmd = scan_string()
+    local n = node_new(whatsit_id, latelua_sub)
+    setfield(n, 'data', function() shellescape(cmd) end)
+    node_write(n)
+  end, "global", "protected")
+end
+-- File: l3token.dtx
+do
+  local get_next = token.get_next
+  local get_command = token.get_command
+  local get_index = token.get_index
+  local get_mode = token.get_mode or token.get_index
+  local cmd = token.command_id
+  local set_font = cmd'get_font'
+  local biggest_char = token.biggest_char()
+
+  local mode_below_biggest_char = {}
+  local index_not_nil = {}
+  local mode_not_null = {}
+  local non_primitive = {
+    [cmd'left_brace'] = true,
+    [cmd'right_brace'] = true,
+    [cmd'math_shift'] = true,
+    [cmd'mac_param'] = mode_below_biggest_char,
+    [cmd'sup_mark'] = true,
+    [cmd'sub_mark'] = true,
+    [cmd'endv'] = true,
+    [cmd'spacer'] = true,
+    [cmd'letter'] = true,
+    [cmd'other_char'] = true,
+    [cmd'tab_mark'] = mode_below_biggest_char,
+    [cmd'char_given'] = true,
+    [cmd'math_given'] = true,
+    [cmd'xmath_given'] = true,
+    [cmd'set_font'] = mode_not_null,
+    [cmd'undefined_cs'] = true,
+    [cmd'call'] = true,
+    [cmd'long_call'] = true,
+    [cmd'outer_call'] = true,
+    [cmd'long_outer_call'] = true,
+    [cmd'assign_glue'] = index_not_nil,
+    [cmd'assign_mu_glue'] = index_not_nil,
+    [cmd'assign_toks'] = index_not_nil,
+    [cmd'assign_int'] = index_not_nil,
+    [cmd'assign_attr'] = true,
+    [cmd'assign_dimen'] = index_not_nil,
+  }
+
+  luacmd("__token_if_primitive_lua:N", function()
+    local tok = get_next()
+    local is_non_primitive = non_primitive[get_command(tok)]
+    return put_next(
+           is_non_primitive == true
+             and false_tok
+        or is_non_primitive == nil
+             and true_tok
+        or is_non_primitive == mode_not_null
+             and (get_mode(tok) == 0 and true_tok or false_tok)
+        or is_non_primitive == index_not_nil
+             and (get_index(tok) and false_tok or true_tok)
+        or is_non_primitive == mode_below_biggest_char
+             and (get_mode(tok) > biggest_char and true_tok or false_tok))
+  end, "global")
+end

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty	2020-09-24 20:44:44 UTC (rev 56423)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty	2020-09-24 20:46:14 UTC (rev 56424)
@@ -19,7 +19,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-09-06}%
+\def\ExplFileDate{2020-09-24}%
 \let\ExplLoaderFileDate\ExplFileDate
 \ProvidesPackage{expl3}
   [%



More information about the tex-live-commits mailing list.