texlive[54099] trunk: l3 (4mar20)

commits+karl at tug.org commits+karl at tug.org
Thu Mar 5 02:01:49 CET 2020


Revision: 54099
          http://tug.org/svn/texlive?view=revision&revision=54099
Author:   karl
Date:     2020-03-05 02:01:48 +0100 (Thu, 05 Mar 2020)
Log Message:
-----------
l3 (4mar20)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl
    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/l3news.tex
    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/doc/latex/l3packages/CHANGELOG.md
    trunk/Master/texmf-dist/doc/latex/l3packages/README.md
    trunk/Master/texmf-dist/doc/latex/l3packages/l3keys2e/l3keys2e.pdf
    trunk/Master/texmf-dist/doc/latex/l3packages/xfp/xfp.pdf
    trunk/Master/texmf-dist/doc/latex/l3packages/xfrac/xfrac.pdf
    trunk/Master/texmf-dist/doc/latex/l3packages/xparse/xparse.pdf
    trunk/Master/texmf-dist/doc/latex/l3packages/xtemplate/xtemplate.pdf
    trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
    trunk/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx
    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/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/l3final.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.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/source/latex/l3packages/l3keys2e/l3keys2e.dtx
    trunk/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx
    trunk/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx
    trunk/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
    trunk/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx
    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.sty
    trunk/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty
    trunk/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty
    trunk/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty
    trunk/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty
    trunk/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty

Modified: trunk/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl	2020-03-05 01:01:48 UTC (rev 54099)
@@ -1,12 +1,12 @@
 #!/usr/bin/env perl
-# $Id: tlmgr.pl 54001 2020-03-02 17:58:52Z karl $
+# $Id: tlmgr.pl 54087 2020-03-05 00:48:55Z preining $
 #
 # Copyright 2008-2020 Norbert Preining
 # This file is licensed under the GNU General Public License version 2
 # or any later version.
 
-my $svnrev = '$Revision: 54001 $';
-my $datrev = '$Date: 2020-03-02 18:58:52 +0100 (Mon, 02 Mar 2020) $';
+my $svnrev = '$Revision: 54087 $';
+my $datrev = '$Date: 2020-03-05 01:48:55 +0100 (Thu, 05 Mar 2020) $';
 my $tlmgrrevision;
 my $tlmgrversion;
 my $prg;
@@ -7081,6 +7081,11 @@
   # If it should work for 2009 and 2010, please use
   #   minrelease/2009-foobar
   #   release/2010-foobar
+  # One exception: if there *is* an extension like -foobar (-gpg, ..)
+  # we allow the local release to be smaller than the max,
+  # so that additional repos can do
+  #   release/3000-foobar
+  # and be usable with all future releases, too.
   my $texlive_release = $remotetlpdb->config_release;
   my $texlive_minrelease = $remotetlpdb->config_minrelease;
   my $rroot = $remotetlpdb->root;
@@ -7121,13 +7126,18 @@
     # if the release of the installed TL is less than the release
     # of the main remote repository, then
     # warn that one needs to call update-tlmgr-latest.sh --update
+    # We do this only if there is no extension like 2100-gpg etc
     if ($is_main && $TeXLive::TLConfig::ReleaseYear < $texlive_release_year) {
-      info("fail load $location\n") if ($::machinereadable);
-      return (undef, "Local TeX Live ($TeXLive::TLConfig::ReleaseYear)"
-              . " is older than remote repository ($texlive_release_year).\n"
-              . "Cross release updates are only supported with\n"
-              . "  update-tlmgr-latest(.sh/.exe) --update\n"
-              . "See https://tug.org/texlive/upgrade.html for details.")
+      if (length($texlive_release) > 4) {
+        debug("Accepting a newer release as remote due to presence of release extension!\n");
+      } else {
+        info("fail load $location\n") if ($::machinereadable);
+        return (undef, "Local TeX Live ($TeXLive::TLConfig::ReleaseYear)"
+                . " is older than remote repository ($texlive_release_year).\n"
+                . "Cross release updates are only supported with\n"
+                . "  update-tlmgr-latest(.sh/.exe) --update\n"
+                . "See https://tug.org/texlive/upgrade.html for details.")
+      }
     }
   } else {
     # $texlive_minrelease not defined, so only one year is valid
@@ -10001,7 +10011,7 @@
 distribution (L<https://tug.org/texlive>) and both are licensed under the
 GNU General Public License Version 2 or later.
 
-$Id: tlmgr.pl 54001 2020-03-02 17:58:52Z karl $
+$Id: tlmgr.pl 54087 2020-03-05 00:48:55Z preining $
 =cut
 
 # test HTML version: pod2html --cachedir=/tmp tlmgr.pl >/tmp/tlmgr.html

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md	2020-03-05 01:01:48 UTC (rev 54099)
@@ -7,6 +7,18 @@
 
 ## [Unreleased]
 
+## [2020-03-03]
+
+### Added
+- `\tex...:D` coverage for TeX Live 2020 engine changes
+
+### Changed
+- New implementation for `\keyval_parse:NNn` - around 40% speed improvement,
+  also *expandable*
+
+### Fixed
+- Make `expl3` reload-safe for `latexrelease` (see latex3/latex2e#295)
+
 ## [2020-02-25]
 
 ### Changed
@@ -179,7 +191,7 @@
 ## [2019-09-28]
 
 ### Changed
-- Speed up variants and reduce their \tracingall output
+- Speed up variants and reduce their `\tracingall` output
 - Debug and deprecation code are now loaded independently of expl3 core
 - `\file_compare_timestamp:nNn(TF)` now usable in expansion contexts
 - Moved to stable:
@@ -410,7 +422,7 @@
 
 ### Deprecated
 - `\box_(g)set_eq_clear:NN`, replaced by `\box_(g)set_eq_drop:NN`
-- `\(h|v)box_unpack_clear:N`, replaced by `\(h|v)box_unpack_drop:N
+- `\(h|v)box_unpack_clear:N`, replaced by `\(h|v)box_unpack_drop:N`
 - `\tl_(g)set_from_file(_x):Nnn`, replaced by `\file_get:nnN`
 
 ### Fixed
@@ -446,7 +458,7 @@
 
 ### Fixed
 - Correct fp randint with zero argument (see #507)
-- Handling of `\current at color` with (x)dvipdfmx` (see #510)
+- Handling of `\current at color` with `(x)dvipdfmx` (see #510)
 
 ### Removed
 - Support for stand-alone `l3regex`, `l3sort`, `l3srt`, `l3tl-analysis`,
@@ -587,10 +599,10 @@
 ## [2018-04-30]
 
 ### Added
-- Implement \tl_analysis_map_inline:nn
-- Implement \exp_args_generate:n to define new \exp_args:N...
+- Implement `\tl_analysis_map_inline:nn`
+- Implement `\exp_args_generate:n` to define new `\exp_args:N...`
   functions
-- Low-level \int_value:w function
+- Low-level `\int_value:w` function
 - New experimental functions for
   - Building token lists piecewise
   - Fast manipulation of integer arrays
@@ -604,7 +616,7 @@
 - Better documentation of cross-module kernel-internal functions
 - Enable `\char_generate:nn` for active chars
 - Renamed `\tl_show_analysis:(N|n)n` as `\tl_analysis_show:(N|n)n`
-- Change \int_rand:nn (and rand_item functions) to better use
+- Change `\int_rand:nn` (and rand_item functions) to better use
   the RNG
 - Make prg break functions public
 - Make scan marks mechanism public
@@ -635,7 +647,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-02-25...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2020-03-03...HEAD
+[2020-03-03]: https://github.com/latex3/latex3/compare/2020-02-25...2020-03-03
 [2020-02-25]: https://github.com/latex3/latex3/compare/2020-02-21...2020-02-25
 [2020-02-21]: https://github.com/latex3/latex3/compare/2020-02-14...2020-02-21
 [2020-02-14]: https://github.com/latex3/latex3/compare/2020-02-13...2020-02-14

Modified: trunk/Master/texmf-dist/doc/latex/l3kernel/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/README.md	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/README.md	2020-03-05 01:01:48 UTC (rev 54099)
@@ -1,7 +1,7 @@
 LaTeX3 Programming Conventions
 ==============================
 
-Release 2020-02-25
+Release 2020-03-03
 
 Overview
 --------

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-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/interface3.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -54,7 +54,7 @@
          {latex-team at latex-project.org}%
    }%
 }
-\date{Released 2020-02-25}
+\date{Released 2020-03-03}
 
 \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/l3news.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.tex	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3news.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -25,6 +25,14 @@
 \hypersetup{colorlinks}
 \usepackage{bookmark}
 
+\MakeOuterQuote{"}
+
+\pdfstringdefDisableCommands
+  {%
+    \RenewExpandableDocumentCommand \cs { O{} m }
+      {\textbackslash#2}%
+  }
+
 \makeatletter
 \newcounter{issue}
 \renewcommand*{\theissue}{%
@@ -155,6 +163,13 @@
   }{%
     \clearpage
   }%
+  \def\MakeOuterQuote#1{%
+    \if\noexpand"\noexpand#1%
+    \else
+      \@latex at error{Unexpected \string\MakeOuterQuote
+          {\detokenize{#1}}\MessageBreak%
+        Check if output is valid in `l3news\theissue.tex'}%
+    \fi}
   \makeatother
   \loop
   \ifnum\value{issue}<\lastissue

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-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2020-02-25}
+\date{Released 2020-03-03}
 
 \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-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2020-02-25}
+\date{Released 2020-03-03}
 
 \newcommand{\TF}{\textit{(TF)}}
 
@@ -180,4 +180,11 @@
     function was \texttt{N}-type.
 \end{itemize}
 
+\section{February 2020}
+
+\begin{itemize}
+  \item \cs{keyval_parse:NNn} now works by expansion, returning
+    the parsed list inside \cs{exp_not:n}.
+\end{itemize}
+
 \end{document}

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-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -32,7 +32,7 @@
         {latex-team at latex-project.org}%
     }%
 }
-\date{Released 2020-02-25}
+\date{Released 2020-03-03}
 
 \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-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3kernel/source3.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -53,7 +53,7 @@
          {latex-team at latex-project.org}%
    }%
 }
-\date{Released 2020-02-25}
+\date{Released 2020-03-03}
 
 \pagenumbering{roman}
 \maketitle

Modified: trunk/Master/texmf-dist/doc/latex/l3packages/CHANGELOG.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3packages/CHANGELOG.md	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3packages/CHANGELOG.md	2020-03-05 01:01:48 UTC (rev 54099)
@@ -7,6 +7,12 @@
 
 ## [Unreleased]
 
+## [2020-03-03]
+
+### Changed
+- Delimited arguments (`DdRrEet`) now allow control sequence tokens
+  as delimiters (issues #367 and #368)
+
 ## [2020-02-25]
 
 ### Changed
@@ -81,7 +87,8 @@
 - Switch to ISO date format
 - Improve cross-module use of internal functions
 
-[Unreleased]: https://github.com/latex3/latex3/compare/2020-02-25...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2020-03-03...HEAD
+[2020-03-03]: https://github.com/latex3/latex3/compare/2020-02-25...2020-03-03
 [2020-02-25]: https://github.com/latex3/latex3/compare/2020-02-14...2020-02-25
 [2020-02-14]: https://github.com/latex3/latex3/compare/2020-02-08...2020-02-14
 [2020-02-08]: https://github.com/latex3/latex3/compare/2020-02-03...2020-02-08

Modified: trunk/Master/texmf-dist/doc/latex/l3packages/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/l3packages/README.md	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/doc/latex/l3packages/README.md	2020-03-05 01:01:48 UTC (rev 54099)
@@ -1,7 +1,7 @@
 LaTeX3 High-Level Concepts
 ==========================
 
-Release 2020-02-25
+Release 2020-03-03
 
 Overview
 --------

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

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

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

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

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

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/expl3.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -24,7 +24,7 @@
 %
 %<*driver|generic|package|2ekernel>
 %</driver|generic|package|2ekernel>
-\def\ExplFileDate{2020-02-25}%
+\def\ExplFileDate{2020-03-03}%
 %<*driver>
 \documentclass[full]{l3doc}
 \usepackage{graphicx}
@@ -51,7 +51,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -1196,11 +1196,9 @@
 % simply turn it on. We use \tn{@pushfilenameaux} as a marker: it's defined
 % a little later.
 %    \begin{macrocode}
-%<*!2ekernel>
 \ifdefined\@pushfilenameaux
   \ExplSyntaxOn
 \fi
-%</!2ekernel>
 %    \end{macrocode}
 %
 %    \begin{macrocode}
@@ -1279,7 +1277,7 @@
         \sys_load_debug:
         \debug_on:n { log-functions }
       } ,
-    suppress-backend-headers .bool_set_inverse:N
+    suppress-backend-headers .bool_gset_inverse:N
       = \g__kernel_backend_header_bool ,
     suppress-backend-headers .initial:n = false ,
     undo-recent-deprecations .code:n =
@@ -1381,7 +1379,7 @@
 %   saves the rest of the stack and then does the test. The flag here
 %   is not a proper \texttt{bool}, so a low-level test is used.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_status_pop:w #1#2 \q_stop
+\cs_gset_protected:Npn \@@_status_pop:w #1#2 \q_stop
   {
     \tl_set:Nn \l_@@_status_stack_tl {#2}
     \int_if_odd:nTF {#1}
@@ -1397,8 +1395,11 @@
 %   already active, at the end of the package \cs{ExplSyntaxOff} can
 %   safely be called.
 %    \begin{macrocode}
-\tl_new:N \l_@@_status_stack_tl
-\tl_set:Nn \l_@@_status_stack_tl { 0 }
+\tl_if_exist:NF \l_@@_status_stack_tl
+  {
+    \tl_new:N \l_@@_status_stack_tl
+    \tl_set:Nn \l_@@_status_stack_tl { 0 }
+  }
 %    \end{macrocode}
 % \end{variable}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -1606,7 +1606,7 @@
 %
 % \begin{macro}{\use:x}
 %   Fully expands its argument and passes it to the input stream. Uses
-%   the reserved \cs{l_@@_internal_tl} which will be set up in \pkg{l3expan}.
+%   the reserved \cs{l_@@_internal_tl} which we've set up above.
 %    \begin{macrocode}
 \cs_set_protected:Npn \use:x #1
   {
@@ -1621,7 +1621,7 @@
 %    \end{macrocode}
 %
 % \begin{macro}[EXP]{\use:e}
-%   Currently \LuaTeX-only: emulated for older engines.
+%   In non-\LuaTeX engines older than 2019, \cs{expanded} is emulated.
 %    \begin{macrocode}
 \cs_set:Npn \use:e #1 { \tex_expanded:D {#1} }
 \tex_ifdefined:D \tex_expanded:D \tex_else:D

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3box.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3color-base.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -79,7 +79,7 @@
 %
 % \title{The \cls{l3doc} class}
 % \author{\Team}
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 % \maketitle
 % \tableofcontents
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -63,7 +63,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3file.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3final.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3final.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3final.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 % \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-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 % \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-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -40,7 +40,7 @@
 %          {latex-team at latex-project.org}^^A
 %    }^^A
 % }
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -49,7 +49,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3int.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -722,7 +722,7 @@
 %   (\cs{keys_set_known:nnnN}), the key--value entries are returned
 %   relative to this point in the key tree. When it is absent, only the
 %   key name and value are provided. The correct list is returned by
-%   nested calls. 
+%   nested calls.
 % \end{function}
 %
 % \section{Selective key setting}
@@ -891,7 +891,7 @@
 % \end{verbatim}
 % are treated identically.
 %
-% \begin{function}[updated = 2011-09-08]{\keyval_parse:NNn}
+% \begin{function}[EXP,updated = 2020-02-20]{\keyval_parse:NNn}
 %   \begin{syntax}
 %     \cs{keyval_parse:NNn} \meta{function_1} \meta{function_2} \Arg{key--value list}
 %   \end{syntax}
@@ -920,6 +920,11 @@
 %   all). Spaces are trimmed from the ends of the \meta{key} and \meta{value},
 %   then one \emph{outer} set of braces is removed from the \meta{key}
 %   and \meta{value} as part of the processing.
+%   \begin{texnote}
+%     The result is returned within \cs{exp_not:n}, which means that the
+%     converted input stream does not expand further when appearing in an
+%     \texttt{x}-type or \texttt{e}-type argument expansion.
+%   \end{texnote}
 % \end{function}
 %
 % \end{documentation}
@@ -946,234 +951,312 @@
 %<@@=keyval>
 %    \end{macrocode}
 %
-% \begin{variable}{\l_@@_key_tl, \l_@@_value_tl}
-%   The current key name and value.
+% \begin{variable}{\s_@@_nil,\s_@@_mark,\s_@@_stop,\s_@@_tail}
 %    \begin{macrocode}
-\tl_new:N \l_@@_key_tl
-\tl_new:N \l_@@_value_tl
+\scan_new:N \s_@@_nil
+\scan_new:N \s_@@_mark
+\scan_new:N \s_@@_stop
+\scan_new:N \s_@@_tail
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{variable}{\l_@@_sanitise_tl}
-%   A token list variable for dealing with awkward category codes in the
-%   input.
+%   This temporary macro will be used since some of the definitions will need an
+%   active comma or equals sign. Inside of this macro |#1| will be the active
+%   comma and |#2| will be the active equals sign.
 %    \begin{macrocode}
-\tl_new:N \l_@@_sanitise_tl
+\group_begin:
+  \cs_set_protected:Npn \@@_tmp:NN #1#2
+    {
 %    \end{macrocode}
-% \end{variable}
 %
-% \begin{macro}{\keyval_parse:NNn}
-%   The main function starts off by normalising category codes in package mode.
-%   That's relatively \enquote{expensive} so is skipped (hopefully) in format
-%   mode. We then hand off to the parser. The use of \cs{q_mark} here prevents
-%   loss of braces from the key argument. Notice that by passing the two
-%   processor commands along the input stack we avoid the need to track these
-%   at all.
+% \begin{macro}[EXP]{\keyval_parse:NNn}
+%   The main function starts the first of two input loops. The outer loop splits
+%   the key--value list at active commas, the inner loop will do so at other
+%   commas. The use of \cs{s_@@_mark} here prevents loss of braces from the key
+%   argument.
 %    \begin{macrocode}
-\cs_new_protected:Npn \keyval_parse:NNn #1#2#3
-  {
-%<*initex>
-    \@@_loop:NNw #1#2 \q_mark #3 , \q_recursion_tail ,
-%</initex>
-%<*package>
-    \tl_set:Nn \l_@@_sanitise_tl {#3}
-    \@@_sanitise_equals:
-    \@@_sanitise_comma:
-    \exp_after:wN \@@_loop:NNw \exp_after:wN #1 \exp_after:wN #2
-      \exp_after:wN \q_mark \l_@@_sanitise_tl , \q_recursion_tail ,
-%</package>
-  }
+      \cs_new:Npn \keyval_parse:NNn ##1 ##2 ##3
+        {
+          \@@_loop_active:NNw ##1 ##2 \s_@@_mark ##3 #1 \s_@@_tail #1
+        }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_sanitise_equals:, \@@_sanitise_comma:}
-% \begin{macro}
-%   {
-%     \@@_sanitise_equals_auxi:w, \@@_sanitise_equals_auxii:w,
-%     \@@_sanitise_comma_auxi:w, \@@_sanitise_comma_auxii:w,
-%     \@@_sanitise_aux:w
-%   }
-%   A reasonably fast search and replace set up specifically for the active
-%   tokens. The nature of the input is known so everything is hard-coded.
-%   With only two tokens to cover, the speed gain from using dedicated
-%   functions is worth it.
+% \begin{macro}[EXP]{\@@_loop_active:NNw}
+%   First a fast test for the end of the loop is done, it'll gobble everything
+%   up to an \cs{s_@@_mark} immediately followed by an \cs{s_@@_tail}. The loop
+%   ending macro will gobble everything to the last \cs{s_@@_mark} in this
+%   definition.
+%   If the end isn't reached yet, start the second loop splitting at other
+%   comments, and after that one iterate the current loop.
 %    \begin{macrocode}
-%<*package>
-\group_begin:
-  \char_set_catcode_active:n { `\= }
-  \char_set_catcode_active:n { `\, }
-  \cs_new_protected:Npn \@@_sanitise_equals:
-    {
-      \exp_after:wN \@@_sanitise_equals_auxi:w \l_@@_sanitise_tl
-        \q_mark = \q_nil =
-      \exp_after:wN \@@_sanitise_aux:w \l_@@_sanitise_tl
-    }
-    \cs_new_protected:Npn \@@_sanitise_equals_auxi:w #1 =
-      {
-        \tl_set:Nn \l_@@_sanitise_tl {#1}
-        \@@_sanitise_equals_auxii:w
-      }
-    \cs_new_protected:Npn \@@_sanitise_equals_auxii:w #1 =
-      {
-        \if_meaning:w \q_nil #1 \scan_stop:
-        \else:
-          \tl_set:Nx \l_@@_sanitise_tl
+      \cs_new:Npn \@@_loop_active:NNw ##1 ##2 ##3 #1
+        {
+          \@@_if_recursion_tail:w ##3
+            \@@_end_loop_active:w \s_@@_mark \s_@@_tail
+          \@@_loop_other:NNw ##1 ##2 ##3 , \s_@@_tail ,
+          \@@_loop_active:NNw ##1 ##2 \s_@@_mark
+        }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_loop_other:NNw}
+%   The second loop uses the same test for its end as the first loop, next it
+%   tests whether there are other or active equals signs, throwing an error if
+%   there are both. If there are none, test whether the argument is blank or is
+%   a single key. If there are only active equals signs split at those, else
+%   split at others. Finally, iterate the loop.
+%    \begin{macrocode}
+      \cs_new:Npn \@@_loop_other:NNw ##1 ##2 ##3 ,
+        {
+          \@@_if_recursion_tail:w ##3
+            \@@_end_loop_other:w \s_@@_mark \s_@@_tail
+          \@@_if_has_equal_other:w ##3 = \s_@@_stop
+            \@@_has_false:w \s_@@_mark \s_@@_stop \use_i:nn
             {
-              \exp_not:o \l_@@_sanitise_tl
-              \token_to_str:N =
-              \exp_not:n {#1}
+              \@@_if_has_equal_active:w ##3 #2 \s_@@_stop
+                \@@_has_false:w \s_@@_mark \s_@@_stop \use_i:nn
+                \@@_misplaced_equal_error:
+                { \@@_split_other:w ##3 = \s_@@_stop ##2 }
             }
-          \exp_after:wN \@@_sanitise_equals_auxii:w
-        \fi:
-      }
-  \cs_new_protected:Npn \@@_sanitise_comma:
-    {
-      \exp_after:wN \@@_sanitise_comma_auxi:w \l_@@_sanitise_tl
-        \q_mark , \q_nil ,
-      \exp_after:wN \@@_sanitise_aux:w \l_@@_sanitise_tl
-    }
-    \cs_new_protected:Npn \@@_sanitise_comma_auxi:w #1 ,
-      {
-        \tl_set:Nn \l_@@_sanitise_tl {#1}
-        \@@_sanitise_comma_auxii:w
-      }
-    \cs_new_protected:Npn \@@_sanitise_comma_auxii:w #1 ,
-      {
-        \if_meaning:w \q_nil #1 \scan_stop:
-        \else:
-          \tl_set:Nx \l_@@_sanitise_tl
             {
-              \exp_not:o \l_@@_sanitise_tl
-              \token_to_str:N ,
-              \exp_not:n {#1}
+              \@@_if_has_equal_active:w ##3 #2 \s_@@_stop
+                \@@_has_false:w \s_@@_mark \s_@@_stop \use_i:nn
+                { \@@_split_active:w ##3 #2 \s_@@_stop ##2 }
+                {
+                  \@@_if_blank:w ##3 \s_@@_nil \s_@@_stop
+                    \@@_blank_true:w \s_@@_mark \s_@@_stop \use:n
+                    { \@@_trim:nN { ##3 } \@@_key:nN ##1 }
+                }
             }
-          \exp_after:wN \@@_sanitise_comma_auxii:w
-        \fi:
-      }
+          \@@_loop_other:NNw ##1 ##2 \s_@@_mark
+        }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_split_active:w}
+% \begin{macro}[EXP]{\@@_split_active:nw}
+%   Splits at the first active equals sign and trims the key. Next test whether
+%   there are any more valid split points, if so throw an error and gobble the
+%   remaining \meta{function_2}, which will not yet be gobbled. If there was
+%   only one active equals sign start trimming the spaces off the value and give
+%   control to \cs[no-index]{@@_key_val:nnN}.
+%    \begin{macrocode}
+      \cs_new:Npn \@@_split_active:w ##1 #2
+        {
+          \@@_trim:nN { ##1 } \@@_split_active:nw \s_@@_mark
+        }
+        \cs_new:Npn \@@_split_active:nw ##1 ##2 #2 ##3 \s_@@_stop
+          {
+            \@@_if_empty:w \s_@@_mark ##3 \s_@@_stop
+              \@@_has_false:w \s_@@_mark \s_@@_stop \use_i:nn
+              { \@@_misplaced_equal_error: \use_none:n }
+              { \@@_trim:nN { ##2 } \@@_key_val:nnN { ##1 } }
+          }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_if_has_equal_active:w}
+%   The test for an active equals sign just gobbles tokens until the first
+%   active equals sign and then runs the test for an empty argument.
+%    \begin{macrocode}
+      \cs_new:Npn \@@_if_has_equal_active:w ##1 #2
+        {
+          \@@_if_empty:w \s_@@_mark
+        }
+%    \end{macrocode}
+% \end{macro}
+%
+% We're done with the macros which need active equals signs or commas in their
+% definition, so we can end that scope and call the temporary macro which will
+% do the definitions.
+%    \begin{macrocode}
+    }
+  \char_set_catcode_active:n { `\, }
+  \char_set_catcode_active:n { `\= }
+  \@@_tmp:NN , =
 \group_end:
-\cs_new_protected:Npn \@@_sanitise_aux:w #1 \q_mark
-  { \tl_set:Nn \l_@@_sanitise_tl {#1} }
-%</package>
 %    \end{macrocode}
+%
+% \begin{macro}[EXP]{\@@_end_loop_active:w,\@@_end_loop_other:w}
+%   Both of these macros just have to gobble a few tokens to remove the reminder
+%   of the loops current iteration. We do this in a pretty static manner,
+%   explicitly stating every token we know beforehand because this is slightly
+%   faster.
+%    \begin{macrocode}
+\cs_new:Npn \@@_end_loop_active:w
+    \s_@@_mark \s_@@_tail
+    \@@_loop_other:NNw #1 , \s_@@_tail ,
+    \@@_loop_active:NNw #2 \s_@@_mark
+  {}
+\cs_new:Npn \@@_end_loop_other:w
+    \s_@@_mark \s_@@_tail
+    \@@_if_has_equal_other:w #1 = \s_@@_stop
+    \@@_has_false:w \s_@@_mark \s_@@_stop \use_i:nn
+    #2
+    \@@_loop_other:NNw #3 \s_@@_mark
+  {}
+%    \end{macrocode}
 % \end{macro}
+%
+% \begin{macro}[EXP]{\@@_split_other:w}
+% \begin{macro}[EXP]{\@@_split_other:nw}
+%   These work exactly as \cs[no-index]{@@_split_active:wN}, just for
+%   equals signs of category other.
+%    \begin{macrocode}
+\cs_new:Npn \@@_split_other:w #1 =
+  {
+    \@@_trim:nN { #1 } \@@_split_other:nw \s_@@_mark
+  }
+  \cs_new:Npn \@@_split_other:nw #1 #2 = #3 \s_@@_stop
+    {
+      \@@_if_empty:w \s_@@_mark #3 \s_@@_stop
+        \@@_has_false:w \s_@@_mark \s_@@_stop \use_i:nn
+        { \@@_misplaced_equal_error: \use_none:n }
+        { \@@_trim:nN { #2 } \@@_key_val:nnN { #1 } }
+    }
+%    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
-% \begin{macro}{\@@_loop:NNw}
-%   A fast test for the end of the loop, remembering to remove the leading
-%   quark first. Assuming that is not the case, look for a key and value then
-%   loop around, re-inserting a leading quark in front of the next position.
+% \begin{macro}[EXP]{\@@_key:nN}
+%   This will get the current key with spaces trimmed and \meta{function_1} as
+%   its arguments. All it has to do is put them in an \cs{exp_not:n} and reorder
+%   them.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_loop:NNw #1#2#3 ,
+\cs_new:Npn \@@_key:nN #1 #2
   {
-    \exp_after:wN \if_meaning:w \exp_after:wN \q_recursion_tail
-      \use_none:n #3 \prg_do_nothing:
-    \else:
-      \@@_split:NNw #1#2#3 == \q_stop
-      \exp_after:wN \@@_loop:NNw \exp_after:wN #1 \exp_after:wN #2
-        \exp_after:wN \q_mark
-    \fi:
+    \exp_not:n { #2 { #1 } }
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_split:NNw, \@@_split_value:NNw}
-% \begin{macro}{\@@_split_tidy:w}
-% \begin{macro}{\@@_action:}
-%   The value is picked up separately from the key so there can be another
-%   quark inserted at the front, keeping braces and allowing both parts to
-%   share the same code paths. The key is found first then there's a check
-%   that there is something there: this is biased to the common case of there
-%   actually being a key. For the value, we first need to see if there is
-%   anything to do: if there is, extract it. The appropriate action is then
-%   inserted in front of the key and value. Doing this using an assignment is
-%   marginally faster than an expansion chain.
+% \begin{macro}[EXP]{\@@_key_val:nnN}
+%   This will get the key name and value with spaces trimmed. It has to
+%   assert that the key name isn't empty. Afterwards put them into an
+%   \cs{exp_not:n} together with \meta{function_2}. If the key is empty they are
+%   gobbled instead.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_split:NNw #1#2#3 =
+\cs_new:Npn \@@_key_val:nnN #1 #2 #3
   {
-    \@@_def:Nn \l_@@_key_tl {#3}
-    \if_meaning:w \l_@@_key_tl \c_empty_tl
-      \exp_after:wN \@@_split_tidy:w
-    \else:
-      \exp_after:wN \@@_split_value:NNw
-        \exp_after:wN #1
-        \exp_after:wN #2
-        \exp_after:wN \q_mark
-    \fi:
+    \@@_if_empty:w \s_@@_mark #2 \s_@@_stop
+      \@@_empty_key:w \s_@@_mark \s_@@_stop
+    \exp_not:n { #3 { #2 } { #1 } }
   }
-\cs_new_protected:Npn \@@_split_value:NNw #1#2#3 = #4 \q_stop
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_if_empty:w,\@@_if_blank:w,\@@_if_recursion_tail:w}
+%   All these tests work by gobbling tokens until a certain combination is met,
+%   which makes them pretty fast. The test for a blank argument should be called
+%   with an arbitrary token following the argument. Each of these utilize the
+%   fact that the argument will contain a leading \cs{s_@@_mark}.
+%    \begin{macrocode}
+\cs_new:Npn \@@_if_empty:w #1 \s_@@_mark \s_@@_stop {}
+\cs_new:Npn \@@_if_blank:w \s_@@_mark #1 { \@@_if_empty:w \s_@@_mark }
+\cs_new:Npn \@@_if_recursion_tail:w #1 \s_@@_mark \s_@@_tail {}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_has_false:w,\@@_blank_true:w,\@@_empty_key:w}
+%   These macros will be called if the tests above didn't gobble them, they
+%   execute the branching.
+%    \begin{macrocode}
+\cs_new:Npn \@@_has_false:w \s_@@_mark \s_@@_stop \use_i:nn #1 #2 { #2 }
+\cs_new:Npn \@@_blank_true:w \s_@@_mark \s_@@_stop \use:n #1 {}
+\cs_new:Npn \@@_empty_key:w \s_@@_mark \s_@@_stop \exp_not:n #1
   {
-    \if:w \scan_stop: \tl_to_str:n {#4} \scan_stop:
-      \cs_set:Npx \@@_action:
-        { \exp_not:N #1 { \exp_not:o \l_@@_key_tl } }
-    \else:
-      \if:w
-        \scan_stop:
-        \__kernel_tl_to_str:w \exp_after:wN { \use_none:n #4 }
-        \scan_stop:
-        \@@_def:Nn \l_@@_value_tl {#3}
-        \cs_set:Npx \@@_action:
-          {
-            \exp_not:N #2
-              { \exp_not:o \l_@@_key_tl }
-              { \exp_not:o \l_@@_value_tl }
-          }
-      \else:
-        \cs_set:Npn \@@_action:
-          {
-            \__kernel_msg_error:nn { kernel }
-              { misplaced-equals-sign }
-          }
-      \fi:
-    \fi:
-    \@@_action:
+    \@@_misplaced_equal_error:
   }
-\cs_new_protected:Npn \@@_split_tidy:w #1 \q_stop
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_if_has_equal_other:w}
+%   Another test that works by gobbling tokens until a specific one is hit.
+%    \begin{macrocode}
+\cs_new:Npn \@@_if_has_equal_other:w #1 =
   {
-    \if:w
-      \scan_stop:
-      \__kernel_tl_to_str:w \exp_after:wN { \use_none:n #1 }
-      \scan_stop:
-    \else:
-      \exp_after:wN \@@_empty_key:
-    \fi:
+    \@@_if_empty:w \s_@@_mark
   }
-\cs_new:Npn \@@_action: { }
-\cs_new_protected:Npn \@@_empty_key:
-  { \__kernel_msg_error:nn { kernel } { misplaced-equals-sign } }
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \end{macro}
 %
-% \begin{macro}{\@@_def:Nn}
-% \begin{macro}[EXP]{\@@_def_aux:n}
-% \begin{macro}[EXP]{\@@_def_aux:w}
-%   First remove the leading quark, then trim spaces off, and finally remove
-%   a set of braces.
+% \begin{macro}[EXP]{\@@_misplaced_equal_error:}
+%   Just throw an error expandably. This is hid inside a macro so that other
+%   macros don't have to gobble so many tokens, which increases speed for
+%   correct input. This will marginally slow down the error case, but that
+%   doesn't have to be fast anyway.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_def:Nn #1#2
+\cs_new:Npn \@@_misplaced_equal_error:
   {
-    \tl_set:Nx #1
-      { \tl_trim_spaces_apply:oN { \use_none:n #2 } \@@_def_aux:n }
+    \__kernel_msg_expandable_error:nn { kernel } { misplaced-equals-sign }
   }
-\cs_new:Npn \@@_def_aux:n #1
-  { \@@_def_aux:w #1 \q_stop }
-\cs_new:Npn \@@_def_aux:w #1 \q_stop { \exp_not:n {#1} }
 %    \end{macrocode}
 % \end{macro}
-% \end{macro}
-% \end{macro}
 %
 % One message for the low level parsing system.
 %    \begin{macrocode}
-\__kernel_msg_new:nnnn { kernel } { misplaced-equals-sign }
+\__kernel_msg_new:nnn { kernel } { misplaced-equals-sign }
   { Misplaced~equals~sign~in~key-value~input~\msg_line_context: }
-  {
-    LaTeX~is~attempting~to~parse~some~key-value~input~but~found~
-    two~equals~signs~not~separated~by~a~comma.
-  }
 %    \end{macrocode}
 %
+% \begin{macro}[EXP]{\@@_trim:nN}
+% \begin{macro}[EXP]
+%   {\@@_trim_auxi:w,\@@_trim_auxii:w,\@@_trim_auxiii:w,\@@_trim_auxiv:w}
+% And an adapted version of \cs{__tl_trim_spaces:nn} which is a bit faster for
+% our use case, as it can strip the braces at the end. This is pretty much the
+% same concept, so I won't comment on it here. The speed gain by using this
+% instead of \cs{tl_trim_spaces_apply:nN} is about 10\,\% of the total time for
+% \cs{keyval_parse:NNn} with one key and one key--value pair, so I think it's
+% worth it.
+%    \begin{macrocode}
+\group_begin:
+  \cs_set_protected:Npn \@@_tmp:n #1
+    {
+      \cs_new:Npn \@@_trim:nN ##1
+        {
+          \@@_trim_auxi:w
+            ##1
+            \s_@@_nil
+            \s_@@_mark #1 {}
+            \s_@@_mark \@@_trim_auxii:w
+            \@@_trim_auxiii:w
+            #1 \s_@@_nil
+            \@@_trim_auxiv:w
+          \s_@@_stop
+        }
+      \cs_new:Npn \@@_trim_auxi:w ##1 \s_@@_mark #1 ##2 \s_@@_mark ##3
+        {
+          ##3
+          \@@_trim_auxi:w
+          \s_@@_mark
+          ##2
+          \s_@@_mark #1 {##1}
+        }
+      \cs_new:Npn \@@_trim_auxii:w \@@_trim_auxi:w \s_@@_mark \s_@@_mark ##1
+        {
+          \@@_trim_auxiii:w
+          ##1
+        }
+      \cs_new:Npn \@@_trim_auxiii:w ##1 #1 \s_@@_nil ##2
+        {
+          ##2
+          ##1 \s_@@_nil
+          \@@_trim_auxiii:w
+        }
+%    \end{macrocode}
+%   This is the one macro which differs from the original definition.
+%    \begin{macrocode}
+      \cs_new:Npn \@@_trim_auxiv:w \s_@@_mark ##1 \s_@@_nil ##2 \s_@@_stop ##3
+        { ##3 { ##1 } }
+    }
+  \@@_tmp:n { ~ }
+\group_end:
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \subsection{Constants and variables}
 %
 %    \begin{macrocode}
@@ -2670,7 +2753,7 @@
   {
     \tl_set:Nx \l_@@_relative_tl
       { \exp_args:No \@@_trim_spaces:n \l_@@_relative_tl }
-    \use:x 
+    \use:x
       {
         \cs_set_protected:Npn \@@_store_unused:w
           ####1 \l_@@_relative_tl /
@@ -2772,7 +2855,6 @@
   {
     \exp_after:wN \@@_trim_spaces_auxi:w \tl_to_str:n {#1}
       / \q_nil \q_stop
-    
   }
 \cs_new:Npn \@@_trim_spaces_auxi:w #1 / #2 \q_stop
   {

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3names.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -804,6 +804,8 @@
   \@@_primitive:NN \dviextension          \tex_dviextension:D
   \@@_primitive:NN \dvifeedback           \tex_dvifeedback:D
   \@@_primitive:NN \dvivariable           \tex_dvivariable:D
+  \@@_primitive:NN \eTeXglueshrinkorder   \tex_eTeXglueshrinkorder:D
+  \@@_primitive:NN \eTeXgluestretchorder  \tex_eTeXgluestretchorder:D
   \@@_primitive:NN \etoksapp              \tex_etoksapp:D
   \@@_primitive:NN \etokspre              \tex_etokspre:D
   \@@_primitive:NN \exceptionpenalty      \tex_exceptionpenalty:D
@@ -1124,9 +1126,11 @@
   \@@_primitive:NN \hfi                   \tex_hfi:D
   \@@_primitive:NN \ifdbox                \tex_ifdbox:D
   \@@_primitive:NN \ifddir                \tex_ifddir:D
+  \@@_primitive:NN \ifjfont               \tex_ifjfont:D
   \@@_primitive:NN \ifmbox                \tex_ifmbox:D
   \@@_primitive:NN \ifmdir                \tex_ifmdir:D
   \@@_primitive:NN \iftbox                \tex_iftbox:D
+  \@@_primitive:NN \iftfont               \tex_iftfont:D
   \@@_primitive:NN \iftdir                \tex_iftdir:D
   \@@_primitive:NN \ifybox                \tex_ifybox:D
   \@@_primitive:NN \ifydir                \tex_ifydir:D
@@ -1171,6 +1175,7 @@
 %    \end{macrocode}
 % Primitives from \upTeX{}.
 %    \begin{macrocode}
+  \@@_primitive:NN \currentcjktoken       \tex_currentcjktoken:D
   \@@_primitive:NN \disablecjktoken       \tex_disablecjktoken:D
   \@@_primitive:NN \enablecjktoken        \tex_enablecjktoken:D
   \@@_primitive:NN \forcecjktoken         \tex_forcecjktoken:D

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3str.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3text.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -44,7 +44,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3token.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -1831,7 +1831,9 @@
       { \tl_to_str:n {#2} }
       { \char_generate:nn {#1} { 12 } }
   }
-\cs_if_exist:NF \tex_Uchar:D
+\bool_lazy_or:nnF
+  { \cs_if_exist_p:N \tex_luatexversion:D }
+  { \cs_if_exist_p:N \tex_XeTeXversion:D }
   {
     \cs_set:Npn \@@_str_change_case:nN #1#2
       { \tl_to_str:n {#2} }

Modified: trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %

Modified: trunk/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3packages/l3keys2e/l3keys2e.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -62,7 +62,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -139,7 +139,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{l3keys2e}{2020-02-25}{}
+\ProvidesExplPackage{l3keys2e}{2020-03-03}{}
   {LaTeX2e option processing using LaTeX3 keys}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3packages/xfp/xfp.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -64,7 +64,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -167,7 +167,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{xfp}{2020-02-25}{}
+\ProvidesExplPackage{xfp}{2020-03-03}{}
   {L3 Floating point unit}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3packages/xfrac/xfrac.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -65,7 +65,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -535,7 +535,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{xfrac}{2020-02-25}{}
+\ProvidesExplPackage{xfrac}{2020-03-03}{}
   {L3 Experimental split-level fractions}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3packages/xparse/xparse.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -67,7 +67,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -130,12 +130,12 @@
 %     Regardless of the input, the argument will be passed to the
 %     internal code without the outer braces. This is the \pkg{xparse}
 %     type specifier for a normal \TeX{} argument.
-%   \item[r] Given as \texttt{r}\meta{char1}\meta{char2}, this denotes a
+%   \item[r] Given as \texttt{r}\meta{token1}\meta{token2}, this denotes a
 %     \enquote{required} delimited argument, where the delimiters are
-%     \meta{char1} and \meta{char2}. If the opening delimiter
-%     \meta{char1} is missing, the default marker |-NoValue-| will be
+%     \meta{token1} and \meta{token2}. If the opening delimiter
+%     \meta{token1} is missing, the default marker |-NoValue-| will be
 %     inserted after a suitable error.
-%   \item[R] Given as \texttt{R}\meta{char1}\meta{char2}\marg{default},
+%   \item[R] Given as \texttt{R}\meta{token1}\meta{token2}\marg{default},
 %     this is a \enquote{required} delimited argument as for~\texttt{r},
 %     but it has a user-definable recovery \meta{default} instead of
 %     |-NoValue-|.
@@ -158,13 +158,13 @@
 %   \item[o] A standard \LaTeX{} optional argument, surrounded with square
 %     brackets, which will supply
 %     the special |-NoValue-| marker if not given (as described later).
-%   \item[d] Given as \texttt{d}\meta{char1}\meta{char2}, an optional
-%     argument which is delimited by \meta{char1} and \meta{char2}.
+%   \item[d] Given as \texttt{d}\meta{token1}\meta{token2}, an optional
+%     argument which is delimited by \meta{token1} and \meta{token2}.
 %     As with \texttt{o}, if no
 %     value is given the special marker |-NoValue-| is returned.
 %   \item[O] Given as \texttt{O}\marg{default}, is like \texttt{o}, but
 %     returns \meta{default} if no value is given.
-%   \item[D] Given as \texttt{D}\meta{char1}\meta{char2}\marg{default},
+%   \item[D] Given as \texttt{D}\meta{token1}\meta{token2}\marg{default},
 %     it is as for \texttt{d}, but returns \meta{default} if no value is given.
 %     Internally, the \texttt{o}, \texttt{d} and \texttt{O} types are
 %     short-cuts to an appropriated-constructed \texttt{D} type argument.
@@ -171,17 +171,17 @@
 %   \item[s] An optional star, which will result in a value
 %     \cs{BooleanTrue} if a star is present and \cs{BooleanFalse}
 %     otherwise (as described later).
-%   \item[t] An optional \meta{char}, which will result in a value
-%     \cs{BooleanTrue} if \meta{char} is present and \cs{BooleanFalse}
-%     otherwise. Given as \texttt{t}\meta{char}.
-%   \item[e] Given as \texttt{e}\marg{chars}, a set of optional
+%   \item[t] An optional \meta{token}, which will result in a value
+%     \cs{BooleanTrue} if \meta{token} is present and \cs{BooleanFalse}
+%     otherwise. Given as \texttt{t}\meta{token}.
+%   \item[e] Given as \texttt{e}\marg{tokens}, a set of optional
 %     \emph{embellishments}, each of which requires a \emph{value}.
 %     If an embellishment is not present, |-NoValue-| is returned.  Each
 %     embellishment gives one argument, ordered as for the list of
-%     \meta{chars} in the argument specification.  All \meta{chars}
+%     \meta{tokens} in the argument specification.  All \meta{tokens}
 %     must be distinct.  \emph{This is an experimental type}.
 %   \item[E] As for \texttt{e} but returns one or more \meta{defaults}
-%     if values are not given: \texttt{E}\marg{chars}\marg{defaults}. See
+%     if values are not given: \texttt{E}\marg{tokens}\marg{defaults}. See
 %     Section~\ref{sec:embellishment} for more details.
 % \end{itemize}
 %
@@ -213,7 +213,9 @@
 %   \foo[[]         % Error: missing closing "]"
 % \end{verbatim}
 % Also note that |{| and |}| cannot be used as delimiters as they are used
-% by \TeX{} as grouping tokens. Arguments to be grabbed inside these tokens
+% by \TeX{} as grouping tokens. Implicit begin- or end-group tokens (\emph{e.g.},
+% |\bgroup| and |\egroup|) are not allowed for delimited argument tipes.
+% Arguments to be grabbed inside these tokens
 % must be created as either \texttt{m}- or \texttt{g}-type arguments.
 %
 % Within delimited arguments, non-balanced or otherwise awkward tokens may
@@ -371,13 +373,13 @@
 % \subsection{Default values for \enquote{embellishments}}
 % \label{sec:embellishment}
 %
-% The \texttt{E}-type argument allows one default value per test character.
+% The \texttt{E}-type argument allows one default value per test token.
 % This is achieved by giving a list of defaults for each entry in the
 % list, for example:
 % \begin{verbatim}
 %   E{^_}{{UP}{DOWN}}
 % \end{verbatim}
-% If the list of default values is \emph{shorter} than the list of test characters,
+% If the list of default values is \emph{shorter} than the list of test tokens,
 % the special |-NoValue-| marker will be returned (as for the \texttt{e}-type
 % argument). Thus for example
 % \begin{verbatim}
@@ -487,6 +489,66 @@
 %     is given: \texttt{G}\marg{default}.
 % \end{itemize}
 %
+% \subsection{Details about argument delimiters}
+%
+% In normal (non-expandable) commands, the delimited types look for the
+% initial delimiter by peeking ahead (using \pkg{expl3}'s |\peek_...|
+% functions) looking for the delimiter token.  The token has to have the
+% same meaning and \enquote{shape} of the token defined as delimiter.
+% There are three possible cases of delimiters: character tokens, control
+% sequence tokens, and active character tokens.  For all practical purposes
+% of this description, active character tokens will behave exactly as
+% control sequence tokens.
+%
+% \subsubsection{Character tokens}
+%
+% A character token is characterised by its character code, and its meaning
+% is the category code~(|\catcode|).  When a command is defined, the meaning
+% of the character token is fixed into the definition of the command and
+% cannot change.  A command will correctly see an argument delimiter if
+% the open delimiter has the same character and category codes as at the
+% time of the definition.  For example in:
+% \begin{verbatim}
+%   \NewDocumentCommand { \foobar } { D<>{default} } {(#1)}
+%   \foobar <hello> \par
+%   \char_set_catcode_letter:N <
+%   \foobar <hello>
+% \end{verbatim}
+% the output would be:
+% \begin{verbatim}
+%   (hello)
+%   (default)<hello>
+% \end{verbatim}
+% as the open-delimter |<| changed in meaning between the two calls to
+% |\foobar|, so the second one doesn't see the |<| as a valid delimiter.
+% Commands assume that if a valid open-delimiter was found, a matching
+% close-delimiter will also be there.  If it is not (either by being
+% omitted or by changing in meaning), a low-level \TeX{} error is raised
+% and the command call is aborted.
+%
+% \subsubsection{Control sequence tokens}
+%
+% A control sequence (or control character) token is characterised by is
+% its name, and its meaning is its definition.
+% A token cannot have two different meanings at the same time.
+% When a control sequence is defined as delimiter in a command,
+% it will be detected as delimiter whenever the control sequence name
+% is found in the document regardless of its current definition.
+% For example in:
+% \begin{verbatim}
+%   \cs_set:Npn \x { abc }
+%   \NewDocumentCommand { \foobar } { D\x\y{default} } {(#1)}
+%   \foobar \x hello\y \par
+%   \cs_set:Npn \x { def }
+%   \foobar \x hello\y
+% \end{verbatim}
+% the output would be:
+% \begin{verbatim}
+%   (hello)
+%   (hello)
+% \end{verbatim}
+% with both calls to the command seeing the delimiter |\x|.
+%
 % \section{Declaring commands and environments}
 %
 % With the concept of an argument specifier defined, it is now
@@ -916,7 +978,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{xparse}{2020-02-25}{}
+\ProvidesExplPackage{xparse}{2020-03-03}{}
   {L3 Experimental document command parser}
 %    \end{macrocode}
 %
@@ -1906,8 +1968,8 @@
 \cs_new_protected:Npn \@@_normalize_type_D:w #1#2#3
   {
     \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
-    \@@_single_char_check:n {#1}
-    \@@_single_char_check:n {#2}
+    \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
+    \@@_single_token_check:n {#2}
     \@@_add_arg_spec:n { D #1 #2 {#3} }
     \tl_put_right:Nn \l_@@_last_delimiters_tl {#1}
     \bool_set_false:N \l_@@_grab_expandably_bool
@@ -1917,7 +1979,8 @@
   {
     \quark_if_recursion_tail_stop_do:nn {#2} { \@@_bad_arg_spec:wn }
     \tl_if_blank:nT {#1} { \@@_bad_arg_spec:wn }
-    \tl_map_function:nN {#1} \@@_single_char_check:n
+    \tl_map_function:nN {#1} \@@_single_token_check:n
+    \tl_map_function:nN {#1} \@@_allowed_token_check:N
     \@@_normalize_E_unique_check:w #1 \q_nil \q_stop
     \int_compare:nNnT { \tl_count:n {#2} } > { \tl_count:n {#1} }
       { \@@_bad_arg_spec:wn }
@@ -1946,7 +2009,7 @@
 \cs_new_protected:Npn \@@_normalize_type_t:w #1
   {
     \quark_if_recursion_tail_stop_do:Nn #1 { \@@_bad_arg_spec:wn }
-    \@@_single_char_check:n {#1}
+    \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
     \tl_put_right:Nx \l_@@_arg_spec_tl
       {
         \bool_if:NT \l_@@_obey_spaces_bool { ! }
@@ -1994,8 +2057,8 @@
 \cs_new_protected:Npn \@@_normalize_type_R:w #1#2#3
   {
     \quark_if_recursion_tail_stop_do:nn {#3} { \@@_bad_arg_spec:wn }
-    \@@_single_char_check:n {#1}
-    \@@_single_char_check:n {#2}
+    \@@_single_token_check:n {#1} \@@_allowed_token_check:N #1
+    \@@_single_token_check:n {#2}
     \@@_delimiter_check:nnn {#1} { R/r } { \tl_to_str:n {#1} }
     \bool_set_false:N \l_@@_grab_expandably_bool
     \@@_add_arg_spec_mandatory:n { R #1 #2 {#3} }
@@ -2042,27 +2105,53 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_single_char_check:n}
-%   Checks that what should be single characters really are single
-%   characters (possibly surrounded by spaces).
+% \begin{macro}{\@@_single_token_check:n}
+%   Checks that the argument is a single (non-space) token (possibly
+%   surrounded by spaces), and aborts the definition otherwise.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_single_char_check:n #1
+\cs_new_protected:Npn \@@_single_token_check:n #1
   {
-    \tl_trim_spaces_apply:nN {#1} \tl_if_single_token:nTF
+    \tl_trim_spaces_apply:nN {#1} \tl_if_single_token:nF
       {
-        \group_begin:
-        \tex_escapechar:D = 92 \scan_stop:
-        \exp_args:Nx \tl_if_single_token:nF
-          { \exp_args:No \tl_to_str:n { \use:nn #1 { } } }
-          {
-            \__kernel_msg_warning:nnxx { xparse } { not-single-char }
-              { \@@_environment_or_command: } { \tl_to_str:n {#1} }
-          }
-        \group_end:
+        \__kernel_msg_error:nnxx { xparse } { not-single-token }
+          { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+        \@@_bad_def:wn
       }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_allowed_token_check:N}
+%   Some tokens are now allowed as delimiters for some argument types,
+%   notably implicit begin/end-group tokens (|\bgroup|/|\egroup|).
+%   The major problem with these tokens is that for |\peek_...| functions,
+%   a literal~|{|$_1$. is virtually indistinguishable from a |\bgroup| or
+%   other token which was |\let| to a~|{|$_1$, and the same goes
+%   for~|}|$_2$.  All other tokens can be easily distingushed from their
+%   implicit counterparts by grabbing them and looking at the string
+%   length (see \cs{@@_token_if_cs:NTF}), but for begin/end group tokens
+%   that is not possible without the risk of mistakenly grabbing the
+%   entire brace group (potentially leading to a~\texttt{!~Runaway argument}
+%   error) or trying to grab a |}|$_2$, leading to a~\texttt{!~Argument
+%   of~\dots~has an extra~|}|}.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_allowed_token_check:N #1
+  {
+    \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+        { \use:n }
+        {
+          \token_if_eq_meaning:NNTF #1 \c_group_end_token
+            { \use:n }
+            { \use_none:n }
+        }
       {
-        \__kernel_msg_error:nnxx { xparse } { not-single-char }
+        \__kernel_msg_error:nnxxx
+          { xparse } { forbidden-implicit-group-token }
           { \@@_environment_or_command: } { \tl_to_str:n {#1} }
+          {
+            \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+              { begin } { end }
+          }
         \@@_bad_def:wn
       }
   }
@@ -2853,12 +2942,12 @@
 \cs_new_protected:Npn \@@_grab_D_obey_spaces:w #1#2#3 \@@_run_code:
   {
     \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected_nopar:Npn
-      \peek_meaning_remove:NTF
+      \@@_peek_meaning_remove:NTF
   }
 \cs_new_protected:Npn \@@_grab_D_long_obey_spaces:w #1#2#3 \@@_run_code:
   {
     \@@_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected:Npn
-      \peek_meaning_remove:NTF
+      \@@_peek_meaning_remove:NTF
   }
 %    \end{macrocode}
 % \begin{macro}{\@@_grab_D_aux:NNnNN}
@@ -2991,6 +3080,12 @@
 %   the grabber. (This assumes that the open and close delimiters are not the
 %   same character with different category codes, but that really should not
 %   happen in any sensible document-level syntax.)
+%   An exception is when |#1| is a control sequence token, in which case the
+%   character-token treatment is no good because if hit with \cs{token_to_str:N}
+%   it would add sputios tokens to the argument. In this case a different
+%   branch is taken. The token inserted is then the same \meta{csname} as |#1|,
+%   but with a space appended, so that the grabber don't see it as another
+%   of the same delimiter.
 %    \begin{macrocode}
 \cs_new_protected_nopar:Npn \@@_grab_D_call:Nw #1
   {
@@ -3000,8 +3095,15 @@
           \l_@@_fn_tl \char_generate:nn { `#1 } { 11 }
       }
       {
-        \exp_after:wN \l_@@_fn_tl
-        \token_to_str:N #1
+        \@@_token_if_cs:NTF #1
+          {
+            \exp_after:wN \l_@@_fn_tl
+            \cs:w \cs_to_str:N #1 ~ \cs_end:
+          }
+          {
+            \exp_after:wN \l_@@_fn_tl
+            \token_to_str:N #1
+          }
       }
   }
 %    \end{macrocode}
@@ -3033,13 +3135,13 @@
   {
     \@@_grab_E:nnNN {#1} {#2}
       \cs_set_protected_nopar:Npn
-      \peek_meaning_remove:NTF
+      \@@_peek_meaning_remove:NTF
   }
 \cs_new_protected:Npn \@@_grab_E_long_obey_spaces:w #1#2 \@@_run_code:
   {
     \@@_grab_E:nnNN {#1} {#2}
       \cs_set_protected:Npn
-      \peek_meaning_remove:NTF
+      \@@_peek_meaning_remove:NTF
   }
 %    \end{macrocode}
 %   A loop is needed here to allow a random ordering of keys. These are
@@ -3294,7 +3396,7 @@
 \cs_new_protected:Npn \@@_grab_t:w
   { \@@_grab_t_aux:NNw \@@_peek_nonspace_remove:NTF }
 \cs_new_protected:Npn \@@_grab_t_obey_spaces:w
-  { \@@_grab_t_aux:NNw \peek_meaning_remove:NTF }
+  { \@@_grab_t_aux:NNw \@@_peek_meaning_remove:NTF }
 \cs_new_protected:Npn \@@_grab_t_aux:NNw #1#2#3 \@@_run_code:
   {
     \tl_set:Nn \l_@@_signature_tl {#3}
@@ -4282,6 +4384,28 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_token_if_cs:NTF}
+%   Based on the definition of \cs{@@_check_definable_aux:nN} above, but
+%   only checks for an actual control sequence (\emph{i.e.},
+%   \cs[no-index]{\meta{anything}}). \cs{tex_escapechar:D} is
+%   temporarily changed to a known value and then it checks if
+%   |\string#1| contains more than one character: if it does, it's a
+%   control sequence.  This test differs from \cs{token_if_cs:NTF} for
+%   example in \verb|\token_if_cs:NTF \c_group_begin_token {T}{F}|,
+%   where \cs{token_if_cs:NTF} returns false.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_token_if_cs:NTF #1
+  {
+    \group_begin:
+      \int_set:Nn \tex_escapechar:D { 92 }
+      \exp_args:Nx \tl_if_empty:nTF
+          { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
+        { \group_end: \use_ii:nn }
+        { \group_end: \use_i:nn }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\@@_tl_mapthread_function:NNN, \@@_tl_mapthread_function:nnN}
 % \begin{macro}{\@@_tl_mapthread_loop:w}
 %   Analogue of \cs{seq_mapthread_function:NNN} for token lists.
@@ -4351,9 +4475,9 @@
 %   \cs{peek_meaning_remove:NTF}.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_peek_nonspace:NTF
-  { \@@_peek_nonspace_aux:nNNTF { } \peek_meaning:NTF }
+  { \@@_peek_nonspace_aux:nNNTF { } \@@_peek_meaning:NTF }
 \cs_new_protected:Npn \@@_peek_nonspace_remove:NTF
-  { \@@_peek_nonspace_aux:nNNTF { } \peek_meaning_remove:NTF }
+  { \@@_peek_nonspace_aux:nNNTF { } \@@_peek_meaning_remove:NTF }
 \cs_new_protected:Npn \@@_peek_nonspace_aux:nNNTF #1#2#3#4#5
   {
     \peek_meaning_remove:NTF \c_space_token
@@ -4363,6 +4487,55 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_peek_meaning:NTF, \@@_peek_meaning_remove:NTF}
+% \begin{macro}{\@@_peek_cs_check_equal:NNN, \@@_peek_meaning_aux:NNTF, \@@_peek_true_remove:NNw}
+%   Peek ahead for a token with a given meaning.  In case the search
+%   token is a control sequence, also check that the \meta{csname} is
+%   the same as the control sequence peeked at.  This extra verification
+%   is necessary when the command is delimited by control sequence tokens
+%   (as opposed to character tokens), and we want the the exact same
+%   control sequence to match.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_peek_meaning:NTF
+  { \@@_peek_meaning_aux:NNTF \c_false_bool }
+\cs_new_protected:Npn \@@_peek_meaning_remove:NTF
+  { \@@_peek_meaning_aux:NNTF \c_true_bool }
+\cs_new_protected:Npn \@@_peek_meaning_aux:NNTF #1#2#3#4
+  {
+    \tl_set:Nn \l_@@_tmpa_tl {#3}
+    \tl_set:Nn \l_@@_tmpb_tl {#4}
+    \peek_meaning:NTF #2
+      {
+        \token_if_eq_meaning:NNTF #2 \c_group_begin_token
+          { \@@_peek_true_remove:Nw #1 }
+          {
+            \@@_token_if_cs:NTF #2
+              { \@@_peek_cs_check_equal:NNN #1 #2 }
+              { \@@_peek_true_remove:Nw #1 }
+          }
+      }
+      { \l_@@_tmpb_tl }
+  }
+\cs_new_protected:Npn \@@_peek_cs_check_equal:NNN #1#2#3
+  {
+    \str_if_eq:nnTF {#2} {#3}
+      { \@@_peek_true_remove:Nw #1 }
+      { \l_@@_tmpb_tl }
+    #3
+  }
+\cs_new_protected:Npn \@@_peek_true_remove:Nw #1
+  {
+    \bool_if:NTF #1
+      {
+        \tex_afterassignment:D \l_@@_tmpa_tl
+        \cs_set_eq:NN \@@_tmp:w
+      }
+      { \l_@@_tmpa_tl }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \subsection{Messages}
 %
 % \begin{macro}{\@@_environment_or_command:}
@@ -4493,16 +4666,23 @@
     token.~Perhaps~a~backslash~is~missing?
     \c_@@_ignore_def_tl
   }
-\__kernel_msg_new:nnnn { xparse } { not-single-char }
+\__kernel_msg_new:nnnn { xparse } { not-single-token }
   {
     Argument~delimiter~'#2'~for~the~#1~should~be~
-    a~single~character.
+    a~single~non-space~token.
   }
   {
     The~argument~specification~provided~was~not~valid:~in~a~place~
-    where~a~single~character~is~required,~LaTeX~found~'#2'.
+    where~a~single~token~is~required,~LaTeX~found~'#2'.
     \c_@@_ignore_def_tl
   }
+\__kernel_msg_new:nnnn { xparse } { forbidden-implicit-group-token }
+  { Argument~delimiter~'#2'~for~the~#1~is~not~allowed. }
+  {
+    The~argument~specification~provided~was~not~valid:~the~implicit~
+    #3-group~token~'#2'~is~not~allowed~as~an~argument~delimiter.
+    \c_@@_ignore_def_tl
+  }
 \__kernel_msg_new:nnnn { xparse } { processor-in-expandable }
   { Argument~processor~'>{#2}'~cannot~be~used~for~the~expandable~command~'#1'. }
   {

Modified: trunk/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/source/latex/l3packages/xtemplate/xtemplate.dtx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -63,7 +63,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2020-02-25}
+% \date{Released 2020-03-03}
 %
 % \maketitle
 %
@@ -682,7 +682,7 @@
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\ProvidesExplPackage{xtemplate}{2020-02-25}{}
+\ProvidesExplPackage{xtemplate}{2020-03-03}{}
   {L3 Experimental prototype document functions}
 %    \end{macrocode}
 %

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -67,7 +67,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-02-25}%
+\def\ExplFileDate{2020-03-03}%
 \begingroup
   \def\next{\endgroup}%
   \expandafter\ifx\csname PackageError\endcsname\relax
@@ -928,6 +928,8 @@
   \__kernel_primitive:NN \dviextension          \tex_dviextension:D
   \__kernel_primitive:NN \dvifeedback           \tex_dvifeedback:D
   \__kernel_primitive:NN \dvivariable           \tex_dvivariable:D
+  \__kernel_primitive:NN \eTeXglueshrinkorder   \tex_eTeXglueshrinkorder:D
+  \__kernel_primitive:NN \eTeXgluestretchorder  \tex_eTeXgluestretchorder:D
   \__kernel_primitive:NN \etoksapp              \tex_etoksapp:D
   \__kernel_primitive:NN \etokspre              \tex_etokspre:D
   \__kernel_primitive:NN \exceptionpenalty      \tex_exceptionpenalty:D
@@ -1236,9 +1238,11 @@
   \__kernel_primitive:NN \hfi                   \tex_hfi:D
   \__kernel_primitive:NN \ifdbox                \tex_ifdbox:D
   \__kernel_primitive:NN \ifddir                \tex_ifddir:D
+  \__kernel_primitive:NN \ifjfont               \tex_ifjfont:D
   \__kernel_primitive:NN \ifmbox                \tex_ifmbox:D
   \__kernel_primitive:NN \ifmdir                \tex_ifmdir:D
   \__kernel_primitive:NN \iftbox                \tex_iftbox:D
+  \__kernel_primitive:NN \iftfont               \tex_iftfont:D
   \__kernel_primitive:NN \iftdir                \tex_iftdir:D
   \__kernel_primitive:NN \ifybox                \tex_ifybox:D
   \__kernel_primitive:NN \ifydir                \tex_ifydir:D
@@ -1280,6 +1284,7 @@
   \__kernel_primitive:NN \ybaselineshift        \tex_ybaselineshift:D
   \__kernel_primitive:NN \yoko                  \tex_yoko:D
   \__kernel_primitive:NN \vfi                   \tex_vfi:D
+  \__kernel_primitive:NN \currentcjktoken       \tex_currentcjktoken:D
   \__kernel_primitive:NN \disablecjktoken       \tex_disablecjktoken:D
   \__kernel_primitive:NN \enablecjktoken        \tex_enablecjktoken:D
   \__kernel_primitive:NN \forcecjktoken         \tex_forcecjktoken:D
@@ -8856,7 +8861,9 @@
       { \tl_to_str:n {#2} }
       { \char_generate:nn {#1} { 12 } }
   }
-\cs_if_exist:NF \tex_Uchar:D
+\bool_lazy_or:nnF
+  { \cs_if_exist_p:N \tex_luatexversion:D }
+  { \cs_if_exist_p:N \tex_XeTeXversion:D }
   {
     \cs_set:Npn \__char_str_change_case:nN #1#2
       { \tl_to_str:n {#2} }
@@ -12523,147 +12530,159 @@
 \muskip_new:N \g_tmpa_muskip
 \muskip_new:N \g_tmpb_muskip
 %% File: l3keys.dtx
-\tl_new:N \l__keyval_key_tl
-\tl_new:N \l__keyval_value_tl
-\tl_new:N \l__keyval_sanitise_tl
-\cs_new_protected:Npn \keyval_parse:NNn #1#2#3
-  {
-    \tl_set:Nn \l__keyval_sanitise_tl {#3}
-    \__keyval_sanitise_equals:
-    \__keyval_sanitise_comma:
-    \exp_after:wN \__keyval_loop:NNw \exp_after:wN #1 \exp_after:wN #2
-      \exp_after:wN \q_mark \l__keyval_sanitise_tl , \q_recursion_tail ,
-  }
+\scan_new:N \s__keyval_nil
+\scan_new:N \s__keyval_mark
+\scan_new:N \s__keyval_stop
+\scan_new:N \s__keyval_tail
 \group_begin:
-  \char_set_catcode_active:n { `\= }
-  \char_set_catcode_active:n { `\, }
-  \cs_new_protected:Npn \__keyval_sanitise_equals:
+  \cs_set_protected:Npn \__keyval_tmp:NN #1#2
     {
-      \exp_after:wN \__keyval_sanitise_equals_auxi:w \l__keyval_sanitise_tl
-        \q_mark = \q_nil =
-      \exp_after:wN \__keyval_sanitise_aux:w \l__keyval_sanitise_tl
-    }
-    \cs_new_protected:Npn \__keyval_sanitise_equals_auxi:w #1 =
-      {
-        \tl_set:Nn \l__keyval_sanitise_tl {#1}
-        \__keyval_sanitise_equals_auxii:w
-      }
-    \cs_new_protected:Npn \__keyval_sanitise_equals_auxii:w #1 =
-      {
-        \if_meaning:w \q_nil #1 \scan_stop:
-        \else:
-          \tl_set:Nx \l__keyval_sanitise_tl
+      \cs_new:Npn \keyval_parse:NNn ##1 ##2 ##3
+        {
+          \__keyval_loop_active:NNw ##1 ##2 \s__keyval_mark ##3 #1 \s__keyval_tail #1
+        }
+      \cs_new:Npn \__keyval_loop_active:NNw ##1 ##2 ##3 #1
+        {
+          \__keyval_if_recursion_tail:w ##3
+            \__keyval_end_loop_active:w \s__keyval_mark \s__keyval_tail
+          \__keyval_loop_other:NNw ##1 ##2 ##3 , \s__keyval_tail ,
+          \__keyval_loop_active:NNw ##1 ##2 \s__keyval_mark
+        }
+      \cs_new:Npn \__keyval_loop_other:NNw ##1 ##2 ##3 ,
+        {
+          \__keyval_if_recursion_tail:w ##3
+            \__keyval_end_loop_other:w \s__keyval_mark \s__keyval_tail
+          \__keyval_if_has_equal_other:w ##3 = \s__keyval_stop
+            \__keyval_has_false:w \s__keyval_mark \s__keyval_stop \use_i:nn
             {
-              \exp_not:o \l__keyval_sanitise_tl
-              \token_to_str:N =
-              \exp_not:n {#1}
+              \__keyval_if_has_equal_active:w ##3 #2 \s__keyval_stop
+                \__keyval_has_false:w \s__keyval_mark \s__keyval_stop \use_i:nn
+                \__keyval_misplaced_equal_error:
+                { \__keyval_split_other:w ##3 = \s__keyval_stop ##2 }
             }
-          \exp_after:wN \__keyval_sanitise_equals_auxii:w
-        \fi:
-      }
-  \cs_new_protected:Npn \__keyval_sanitise_comma:
-    {
-      \exp_after:wN \__keyval_sanitise_comma_auxi:w \l__keyval_sanitise_tl
-        \q_mark , \q_nil ,
-      \exp_after:wN \__keyval_sanitise_aux:w \l__keyval_sanitise_tl
-    }
-    \cs_new_protected:Npn \__keyval_sanitise_comma_auxi:w #1 ,
-      {
-        \tl_set:Nn \l__keyval_sanitise_tl {#1}
-        \__keyval_sanitise_comma_auxii:w
-      }
-    \cs_new_protected:Npn \__keyval_sanitise_comma_auxii:w #1 ,
-      {
-        \if_meaning:w \q_nil #1 \scan_stop:
-        \else:
-          \tl_set:Nx \l__keyval_sanitise_tl
             {
-              \exp_not:o \l__keyval_sanitise_tl
-              \token_to_str:N ,
-              \exp_not:n {#1}
+              \__keyval_if_has_equal_active:w ##3 #2 \s__keyval_stop
+                \__keyval_has_false:w \s__keyval_mark \s__keyval_stop \use_i:nn
+                { \__keyval_split_active:w ##3 #2 \s__keyval_stop ##2 }
+                {
+                  \__keyval_if_blank:w ##3 \s__keyval_nil \s__keyval_stop
+                    \__keyval_blank_true:w \s__keyval_mark \s__keyval_stop \use:n
+                    { \__keyval_trim:nN { ##3 } \__keyval_key:nN ##1 }
+                }
             }
-          \exp_after:wN \__keyval_sanitise_comma_auxii:w
-        \fi:
-      }
+          \__keyval_loop_other:NNw ##1 ##2 \s__keyval_mark
+        }
+      \cs_new:Npn \__keyval_split_active:w ##1 #2
+        {
+          \__keyval_trim:nN { ##1 } \__keyval_split_active:nw \s__keyval_mark
+        }
+        \cs_new:Npn \__keyval_split_active:nw ##1 ##2 #2 ##3 \s__keyval_stop
+          {
+            \__keyval_if_empty:w \s__keyval_mark ##3 \s__keyval_stop
+              \__keyval_has_false:w \s__keyval_mark \s__keyval_stop \use_i:nn
+              { \__keyval_misplaced_equal_error: \use_none:n }
+              { \__keyval_trim:nN { ##2 } \__keyval_key_val:nnN { ##1 } }
+          }
+      \cs_new:Npn \__keyval_if_has_equal_active:w ##1 #2
+        {
+          \__keyval_if_empty:w \s__keyval_mark
+        }
+    }
+  \char_set_catcode_active:n { `\, }
+  \char_set_catcode_active:n { `\= }
+  \__keyval_tmp:NN , =
 \group_end:
-\cs_new_protected:Npn \__keyval_sanitise_aux:w #1 \q_mark
-  { \tl_set:Nn \l__keyval_sanitise_tl {#1} }
-\cs_new_protected:Npn \__keyval_loop:NNw #1#2#3 ,
+\cs_new:Npn \__keyval_end_loop_active:w
+    \s__keyval_mark \s__keyval_tail
+    \__keyval_loop_other:NNw #1 , \s__keyval_tail ,
+    \__keyval_loop_active:NNw #2 \s__keyval_mark
+  {}
+\cs_new:Npn \__keyval_end_loop_other:w
+    \s__keyval_mark \s__keyval_tail
+    \__keyval_if_has_equal_other:w #1 = \s__keyval_stop
+    \__keyval_has_false:w \s__keyval_mark \s__keyval_stop \use_i:nn
+    #2
+    \__keyval_loop_other:NNw #3 \s__keyval_mark
+  {}
+\cs_new:Npn \__keyval_split_other:w #1 =
   {
-    \exp_after:wN \if_meaning:w \exp_after:wN \q_recursion_tail
-      \use_none:n #3 \prg_do_nothing:
-    \else:
-      \__keyval_split:NNw #1#2#3 == \q_stop
-      \exp_after:wN \__keyval_loop:NNw \exp_after:wN #1 \exp_after:wN #2
-        \exp_after:wN \q_mark
-    \fi:
+    \__keyval_trim:nN { #1 } \__keyval_split_other:nw \s__keyval_mark
   }
-\cs_new_protected:Npn \__keyval_split:NNw #1#2#3 =
+  \cs_new:Npn \__keyval_split_other:nw #1 #2 = #3 \s__keyval_stop
+    {
+      \__keyval_if_empty:w \s__keyval_mark #3 \s__keyval_stop
+        \__keyval_has_false:w \s__keyval_mark \s__keyval_stop \use_i:nn
+        { \__keyval_misplaced_equal_error: \use_none:n }
+        { \__keyval_trim:nN { #2 } \__keyval_key_val:nnN { #1 } }
+    }
+\cs_new:Npn \__keyval_key:nN #1 #2
   {
-    \__keyval_def:Nn \l__keyval_key_tl {#3}
-    \if_meaning:w \l__keyval_key_tl \c_empty_tl
-      \exp_after:wN \__keyval_split_tidy:w
-    \else:
-      \exp_after:wN \__keyval_split_value:NNw
-        \exp_after:wN #1
-        \exp_after:wN #2
-        \exp_after:wN \q_mark
-    \fi:
+    \exp_not:n { #2 { #1 } }
   }
-\cs_new_protected:Npn \__keyval_split_value:NNw #1#2#3 = #4 \q_stop
+\cs_new:Npn \__keyval_key_val:nnN #1 #2 #3
   {
-    \if:w \scan_stop: \tl_to_str:n {#4} \scan_stop:
-      \cs_set:Npx \__keyval_action:
-        { \exp_not:N #1 { \exp_not:o \l__keyval_key_tl } }
-    \else:
-      \if:w
-        \scan_stop:
-        \__kernel_tl_to_str:w \exp_after:wN { \use_none:n #4 }
-        \scan_stop:
-        \__keyval_def:Nn \l__keyval_value_tl {#3}
-        \cs_set:Npx \__keyval_action:
-          {
-            \exp_not:N #2
-              { \exp_not:o \l__keyval_key_tl }
-              { \exp_not:o \l__keyval_value_tl }
-          }
-      \else:
-        \cs_set:Npn \__keyval_action:
-          {
-            \__kernel_msg_error:nn { kernel }
-              { misplaced-equals-sign }
-          }
-      \fi:
-    \fi:
-    \__keyval_action:
+    \__keyval_if_empty:w \s__keyval_mark #2 \s__keyval_stop
+      \__keyval_empty_key:w \s__keyval_mark \s__keyval_stop
+    \exp_not:n { #3 { #2 } { #1 } }
   }
-\cs_new_protected:Npn \__keyval_split_tidy:w #1 \q_stop
+\cs_new:Npn \__keyval_if_empty:w #1 \s__keyval_mark \s__keyval_stop {}
+\cs_new:Npn \__keyval_if_blank:w \s__keyval_mark #1 { \__keyval_if_empty:w \s__keyval_mark }
+\cs_new:Npn \__keyval_if_recursion_tail:w #1 \s__keyval_mark \s__keyval_tail {}
+\cs_new:Npn \__keyval_has_false:w \s__keyval_mark \s__keyval_stop \use_i:nn #1 #2 { #2 }
+\cs_new:Npn \__keyval_blank_true:w \s__keyval_mark \s__keyval_stop \use:n #1 {}
+\cs_new:Npn \__keyval_empty_key:w \s__keyval_mark \s__keyval_stop \exp_not:n #1
   {
-    \if:w
-      \scan_stop:
-      \__kernel_tl_to_str:w \exp_after:wN { \use_none:n #1 }
-      \scan_stop:
-    \else:
-      \exp_after:wN \__keyval_empty_key:
-    \fi:
+    \__keyval_misplaced_equal_error:
   }
-\cs_new:Npn \__keyval_action: { }
-\cs_new_protected:Npn \__keyval_empty_key:
-  { \__kernel_msg_error:nn { kernel } { misplaced-equals-sign } }
-\cs_new_protected:Npn \__keyval_def:Nn #1#2
+\cs_new:Npn \__keyval_if_has_equal_other:w #1 =
   {
-    \tl_set:Nx #1
-      { \tl_trim_spaces_apply:oN { \use_none:n #2 } \__keyval_def_aux:n }
+    \__keyval_if_empty:w \s__keyval_mark
   }
-\cs_new:Npn \__keyval_def_aux:n #1
-  { \__keyval_def_aux:w #1 \q_stop }
-\cs_new:Npn \__keyval_def_aux:w #1 \q_stop { \exp_not:n {#1} }
-\__kernel_msg_new:nnnn { kernel } { misplaced-equals-sign }
-  { Misplaced~equals~sign~in~key-value~input~\msg_line_context: }
+\cs_new:Npn \__keyval_misplaced_equal_error:
   {
-    LaTeX~is~attempting~to~parse~some~key-value~input~but~found~
-    two~equals~signs~not~separated~by~a~comma.
+    \__kernel_msg_expandable_error:nn { kernel } { misplaced-equals-sign }
   }
+\__kernel_msg_new:nnn { kernel } { misplaced-equals-sign }
+  { Misplaced~equals~sign~in~key-value~input~\msg_line_context: }
+\group_begin:
+  \cs_set_protected:Npn \__keyval_tmp:n #1
+    {
+      \cs_new:Npn \__keyval_trim:nN ##1
+        {
+          \__keyval_trim_auxi:w
+            ##1
+            \s__keyval_nil
+            \s__keyval_mark #1 {}
+            \s__keyval_mark \__keyval_trim_auxii:w
+            \__keyval_trim_auxiii:w
+            #1 \s__keyval_nil
+            \__keyval_trim_auxiv:w
+          \s__keyval_stop
+        }
+      \cs_new:Npn \__keyval_trim_auxi:w ##1 \s__keyval_mark #1 ##2 \s__keyval_mark ##3
+        {
+          ##3
+          \__keyval_trim_auxi:w
+          \s__keyval_mark
+          ##2
+          \s__keyval_mark #1 {##1}
+        }
+      \cs_new:Npn \__keyval_trim_auxii:w \__keyval_trim_auxi:w \s__keyval_mark \s__keyval_mark ##1
+        {
+          \__keyval_trim_auxiii:w
+          ##1
+        }
+      \cs_new:Npn \__keyval_trim_auxiii:w ##1 #1 \s__keyval_nil ##2
+        {
+          ##2
+          ##1 \s__keyval_nil
+          \__keyval_trim_auxiii:w
+        }
+      \cs_new:Npn \__keyval_trim_auxiv:w \s__keyval_mark ##1 \s__keyval_nil ##2 \s__keyval_stop ##3
+        { ##3 { ##1 } }
+    }
+  \__keyval_tmp:n { ~ }
+\group_end:
 \str_const:Nn \c__keys_code_root_str     { key~code~>~ }
 \str_const:Nn \c__keys_default_root_str  { key~default~>~ }
 \str_const:Nn \c__keys_groups_root_str   { key~groups~>~ }
@@ -13590,7 +13609,6 @@
   {
     \exp_after:wN \__keys_trim_spaces_auxi:w \tl_to_str:n {#1}
       / \q_nil \q_stop
-
   }
 \cs_new:Npn \__keys_trim_spaces_auxi:w #1 / #2 \q_stop
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex	2020-03-05 01:01:48 UTC (rev 54099)
@@ -19,7 +19,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-02-25}%
+\def\ExplFileDate{2020-03-03}%
 \let\ExplLoaderFileDate\ExplFileDate
 \begingroup
   \def\tempa{LaTeX2e}%

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx	2020-03-05 01:01:48 UTC (rev 54099)
@@ -19,7 +19,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-02-25}%
+\def\ExplFileDate{2020-03-03}%
 \let\ExplLoaderFileDate\ExplFileDate
 \everyjob\expandafter{\the\everyjob
   \message{L3 programming layer <\ExplFileDate>}%
@@ -50,6 +50,9 @@
 \expandafter\ifx\csname tex\string _let:D\endcsname\relax
   \expandafter\endinput
 \fi
+\ifdefined\@pushfilenameaux
+  \ExplSyntaxOn
+\fi
 \cs_if_exist:NF \c__expl_def_ext_tl
   { \tl_const:Nn \c__expl_def_ext_tl { def } }
 \cs_gset_protected:Npn \__kernel_sys_configuration_load:n #1
@@ -76,7 +79,7 @@
         \sys_load_debug:
         \debug_on:n { log-functions }
       } ,
-    suppress-backend-headers .bool_set_inverse:N
+    suppress-backend-headers .bool_gset_inverse:N
       = \g__kernel_backend_header_bool ,
     suppress-backend-headers .initial:n = false ,
     undo-recent-deprecations .code:n =
@@ -129,7 +132,7 @@
       { \ExplSyntaxOff }
       { \exp_after:wN \__expl_status_pop:w \l__expl_status_stack_tl \q_stop }
   }
-\cs_new_protected:Npn \__expl_status_pop:w #1#2 \q_stop
+\cs_gset_protected:Npn \__expl_status_pop:w #1#2 \q_stop
   {
     \tl_set:Nn \l__expl_status_stack_tl {#2}
     \int_if_odd:nTF {#1}
@@ -136,8 +139,11 @@
       { \ExplSyntaxOn }
       { \ExplSyntaxOff }
   }
-\tl_new:N \l__expl_status_stack_tl
-\tl_set:Nn \l__expl_status_stack_tl { 0 }
+\tl_if_exist:NF \l__expl_status_stack_tl
+  {
+    \tl_new:N \l__expl_status_stack_tl
+    \tl_set:Nn \l__expl_status_stack_tl { 0 }
+  }
 \ExplSyntaxOff
 %% 
 %%

Modified: trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3kernel/expl3.sty	2020-03-05 01:01:48 UTC (rev 54099)
@@ -19,7 +19,7 @@
 %% and all files in that bundle must be distributed together.
 %% 
 %% File: expl3.dtx
-\def\ExplFileDate{2020-02-25}%
+\def\ExplFileDate{2020-03-03}%
 \let\ExplLoaderFileDate\ExplFileDate
 \ProvidesPackage{expl3}
   [%
@@ -94,7 +94,7 @@
         \sys_load_debug:
         \debug_on:n { log-functions }
       } ,
-    suppress-backend-headers .bool_set_inverse:N
+    suppress-backend-headers .bool_gset_inverse:N
       = \g__kernel_backend_header_bool ,
     suppress-backend-headers .initial:n = false ,
     undo-recent-deprecations .code:n =
@@ -149,7 +149,7 @@
       { \ExplSyntaxOff }
       { \exp_after:wN \__expl_status_pop:w \l__expl_status_stack_tl \q_stop }
   }
-\cs_new_protected:Npn \__expl_status_pop:w #1#2 \q_stop
+\cs_gset_protected:Npn \__expl_status_pop:w #1#2 \q_stop
   {
     \tl_set:Nn \l__expl_status_stack_tl {#2}
     \int_if_odd:nTF {#1}
@@ -156,8 +156,11 @@
       { \ExplSyntaxOn }
       { \ExplSyntaxOff }
   }
-\tl_new:N \l__expl_status_stack_tl
-\tl_set:Nn \l__expl_status_stack_tl { 0 }
+\tl_if_exist:NF \l__expl_status_stack_tl
+  {
+    \tl_new:N \l__expl_status_stack_tl
+    \tl_set:Nn \l__expl_status_stack_tl { 0 }
+  }
 \cs_gset_eq:NN \__kernel_sys_configuration_load:n
   \__kernel_sys_configuration_load_std:n
 %% 

Modified: trunk/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty	2020-03-05 01:01:48 UTC (rev 54099)
@@ -32,7 +32,7 @@
       }%
     \endinput
   }
-\ProvidesExplPackage{l3keys2e}{2020-02-25}{}
+\ProvidesExplPackage{l3keys2e}{2020-03-03}{}
   {LaTeX2e option processing using LaTeX3 keys}
 \cs_generate_variant:Nn \clist_put_right:Nn { Nv }
 \cs_generate_variant:Nn \keys_if_exist:nnT  { nx }

Modified: trunk/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3packages/xfp/xfp.sty	2020-03-05 01:01:48 UTC (rev 54099)
@@ -33,7 +33,7 @@
     \endinput
   }
 \RequirePackage{xparse}
-\ProvidesExplPackage{xfp}{2020-02-25}{}
+\ProvidesExplPackage{xfp}{2020-03-03}{}
   {L3 Floating point unit}
 \NewExpandableDocumentCommand \fpeval { m } { \fp_eval:n {#1} }
 \NewExpandableDocumentCommand \inteval { m } { \int_eval:n {#1} }

Modified: trunk/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3packages/xfrac/xfrac.sty	2020-03-05 01:01:48 UTC (rev 54099)
@@ -34,7 +34,7 @@
     \endinput
   }
 \RequirePackage{amstext,graphicx,l3keys2e,textcomp,xparse,xtemplate}
-\ProvidesExplPackage{xfrac}{2020-02-25}{}
+\ProvidesExplPackage{xfrac}{2020-03-03}{}
   {L3 Experimental split-level fractions}
 \keys_define:nn { xfrac }
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3packages/xparse/xparse.sty	2020-03-05 01:01:48 UTC (rev 54099)
@@ -32,7 +32,7 @@
       }%
     \endinput
   }
-\ProvidesExplPackage{xparse}{2020-02-25}{}
+\ProvidesExplPackage{xparse}{2020-03-03}{}
   {L3 Experimental document command parser}
 \tl_new:N \l__xparse_arg_spec_tl
 \tl_new:N \l__xparse_args_tl
@@ -503,8 +503,8 @@
 \cs_new_protected:Npn \__xparse_normalize_type_D:w #1#2#3
   {
     \quark_if_recursion_tail_stop_do:nn {#3} { \__xparse_bad_arg_spec:wn }
-    \__xparse_single_char_check:n {#1}
-    \__xparse_single_char_check:n {#2}
+    \__xparse_single_token_check:n {#1} \__xparse_allowed_token_check:N #1
+    \__xparse_single_token_check:n {#2}
     \__xparse_add_arg_spec:n { D #1 #2 {#3} }
     \tl_put_right:Nn \l__xparse_last_delimiters_tl {#1}
     \bool_set_false:N \l__xparse_grab_expandably_bool
@@ -514,7 +514,8 @@
   {
     \quark_if_recursion_tail_stop_do:nn {#2} { \__xparse_bad_arg_spec:wn }
     \tl_if_blank:nT {#1} { \__xparse_bad_arg_spec:wn }
-    \tl_map_function:nN {#1} \__xparse_single_char_check:n
+    \tl_map_function:nN {#1} \__xparse_single_token_check:n
+    \tl_map_function:nN {#1} \__xparse_allowed_token_check:N
     \__xparse_normalize_E_unique_check:w #1 \q_nil \q_stop
     \int_compare:nNnT { \tl_count:n {#2} } > { \tl_count:n {#1} }
       { \__xparse_bad_arg_spec:wn }
@@ -543,7 +544,7 @@
 \cs_new_protected:Npn \__xparse_normalize_type_t:w #1
   {
     \quark_if_recursion_tail_stop_do:Nn #1 { \__xparse_bad_arg_spec:wn }
-    \__xparse_single_char_check:n {#1}
+    \__xparse_single_token_check:n {#1} \__xparse_allowed_token_check:N #1
     \tl_put_right:Nx \l__xparse_arg_spec_tl
       {
         \bool_if:NT \l__xparse_obey_spaces_bool { ! }
@@ -570,8 +571,8 @@
 \cs_new_protected:Npn \__xparse_normalize_type_R:w #1#2#3
   {
     \quark_if_recursion_tail_stop_do:nn {#3} { \__xparse_bad_arg_spec:wn }
-    \__xparse_single_char_check:n {#1}
-    \__xparse_single_char_check:n {#2}
+    \__xparse_single_token_check:n {#1} \__xparse_allowed_token_check:N #1
+    \__xparse_single_token_check:n {#2}
     \__xparse_delimiter_check:nnn {#1} { R/r } { \tl_to_str:n {#1} }
     \bool_set_false:N \l__xparse_grab_expandably_bool
     \__xparse_add_arg_spec_mandatory:n { R #1 #2 {#3} }
@@ -607,23 +608,32 @@
       { \tl_to_str:n {#1} }
     \__xparse_bad_def:wn
   }
-\cs_new_protected:Npn \__xparse_single_char_check:n #1
+\cs_new_protected:Npn \__xparse_single_token_check:n #1
   {
-    \tl_trim_spaces_apply:nN {#1} \tl_if_single_token:nTF
+    \tl_trim_spaces_apply:nN {#1} \tl_if_single_token:nF
       {
-        \group_begin:
-        \tex_escapechar:D = 92 \scan_stop:
-        \exp_args:Nx \tl_if_single_token:nF
-          { \exp_args:No \tl_to_str:n { \use:nn #1 { } } }
-          {
-            \__kernel_msg_warning:nnxx { xparse } { not-single-char }
-              { \__xparse_environment_or_command: } { \tl_to_str:n {#1} }
-          }
-        \group_end:
+        \__kernel_msg_error:nnxx { xparse } { not-single-token }
+          { \__xparse_environment_or_command: } { \tl_to_str:n {#1} }
+        \__xparse_bad_def:wn
       }
+  }
+\cs_new_protected:Npn \__xparse_allowed_token_check:N #1
+  {
+    \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+        { \use:n }
+        {
+          \token_if_eq_meaning:NNTF #1 \c_group_end_token
+            { \use:n }
+            { \use_none:n }
+        }
       {
-        \__kernel_msg_error:nnxx { xparse } { not-single-char }
+        \__kernel_msg_error:nnxxx
+          { xparse } { forbidden-implicit-group-token }
           { \__xparse_environment_or_command: } { \tl_to_str:n {#1} }
+          {
+            \token_if_eq_meaning:NNTF #1 \c_group_begin_token
+              { begin } { end }
+          }
         \__xparse_bad_def:wn
       }
   }
@@ -1055,12 +1065,12 @@
 \cs_new_protected:Npn \__xparse_grab_D_obey_spaces:w #1#2#3 \__xparse_run_code:
   {
     \__xparse_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected_nopar:Npn
-      \peek_meaning_remove:NTF
+      \__xparse_peek_meaning_remove:NTF
   }
 \cs_new_protected:Npn \__xparse_grab_D_long_obey_spaces:w #1#2#3 \__xparse_run_code:
   {
     \__xparse_grab_D_aux:NNnNN #1 #2 {#3} \cs_set_protected:Npn
-      \peek_meaning_remove:NTF
+      \__xparse_peek_meaning_remove:NTF
   }
 \cs_new_protected:Npn \__xparse_grab_D_aux:NNnNN #1#2#3#4#5
   {
@@ -1134,8 +1144,15 @@
           \l__xparse_fn_tl \char_generate:nn { `#1 } { 11 }
       }
       {
-        \exp_after:wN \l__xparse_fn_tl
-        \token_to_str:N #1
+        \__xparse_token_if_cs:NTF #1
+          {
+            \exp_after:wN \l__xparse_fn_tl
+            \cs:w \cs_to_str:N #1 ~ \cs_end:
+          }
+          {
+            \exp_after:wN \l__xparse_fn_tl
+            \token_to_str:N #1
+          }
       }
   }
 \cs_new_protected:Npn \__xparse_grab_E:w #1#2 \__xparse_run_code:
@@ -1154,13 +1171,13 @@
   {
     \__xparse_grab_E:nnNN {#1} {#2}
       \cs_set_protected_nopar:Npn
-      \peek_meaning_remove:NTF
+      \__xparse_peek_meaning_remove:NTF
   }
 \cs_new_protected:Npn \__xparse_grab_E_long_obey_spaces:w #1#2 \__xparse_run_code:
   {
     \__xparse_grab_E:nnNN {#1} {#2}
       \cs_set_protected:Npn
-      \peek_meaning_remove:NTF
+      \__xparse_peek_meaning_remove:NTF
   }
 \cs_new_protected:Npn \__xparse_grab_E:nnNN #1#2#3#4
   {
@@ -1327,7 +1344,7 @@
 \cs_new_protected:Npn \__xparse_grab_t:w
   { \__xparse_grab_t_aux:NNw \__xparse_peek_nonspace_remove:NTF }
 \cs_new_protected:Npn \__xparse_grab_t_obey_spaces:w
-  { \__xparse_grab_t_aux:NNw \peek_meaning_remove:NTF }
+  { \__xparse_grab_t_aux:NNw \__xparse_peek_meaning_remove:NTF }
 \cs_new_protected:Npn \__xparse_grab_t_aux:NNw #1#2#3 \__xparse_run_code:
   {
     \tl_set:Nn \l__xparse_signature_tl {#3}
@@ -1878,6 +1895,15 @@
       }
     }
 \group_end:
+\cs_new_protected:Npn \__xparse_token_if_cs:NTF #1
+  {
+    \group_begin:
+      \int_set:Nn \tex_escapechar:D { 92 }
+      \exp_args:Nx \tl_if_empty:nTF
+          { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
+        { \group_end: \use_ii:nn }
+        { \group_end: \use_i:nn }
+  }
 \cs_new:Npn \__xparse_tl_mapthread_function:NNN #1#2#3
   {
     \exp_after:wN \exp_after:wN
@@ -1922,9 +1948,9 @@
   }
 \cs_new:Npn \__xparse_cmd_if_xparse_aux:w #1 ~ #2 \q_stop {#1}
 \cs_new_protected:Npn \__xparse_peek_nonspace:NTF
-  { \__xparse_peek_nonspace_aux:nNNTF { } \peek_meaning:NTF }
+  { \__xparse_peek_nonspace_aux:nNNTF { } \__xparse_peek_meaning:NTF }
 \cs_new_protected:Npn \__xparse_peek_nonspace_remove:NTF
-  { \__xparse_peek_nonspace_aux:nNNTF { } \peek_meaning_remove:NTF }
+  { \__xparse_peek_nonspace_aux:nNNTF { } \__xparse_peek_meaning_remove:NTF }
 \cs_new_protected:Npn \__xparse_peek_nonspace_aux:nNNTF #1#2#3#4#5
   {
     \peek_meaning_remove:NTF \c_space_token
@@ -1931,6 +1957,42 @@
       { \__xparse_peek_nonspace_aux:nNNTF { #1 ~ } #2 #3 {#4} {#5} }
       { #2 #3 { #4 } { #5 #1 } }
   }
+\cs_new_protected:Npn \__xparse_peek_meaning:NTF
+  { \__xparse_peek_meaning_aux:NNTF \c_false_bool }
+\cs_new_protected:Npn \__xparse_peek_meaning_remove:NTF
+  { \__xparse_peek_meaning_aux:NNTF \c_true_bool }
+\cs_new_protected:Npn \__xparse_peek_meaning_aux:NNTF #1#2#3#4
+  {
+    \tl_set:Nn \l__xparse_tmpa_tl {#3}
+    \tl_set:Nn \l__xparse_tmpb_tl {#4}
+    \peek_meaning:NTF #2
+      {
+        \token_if_eq_meaning:NNTF #2 \c_group_begin_token
+          { \__xparse_peek_true_remove:Nw #1 }
+          {
+            \__xparse_token_if_cs:NTF #2
+              { \__xparse_peek_cs_check_equal:NNN #1 #2 }
+              { \__xparse_peek_true_remove:Nw #1 }
+          }
+      }
+      { \l__xparse_tmpb_tl }
+  }
+\cs_new_protected:Npn \__xparse_peek_cs_check_equal:NNN #1#2#3
+  {
+    \str_if_eq:nnTF {#2} {#3}
+      { \__xparse_peek_true_remove:Nw #1 }
+      { \l__xparse_tmpb_tl }
+    #3
+  }
+\cs_new_protected:Npn \__xparse_peek_true_remove:Nw #1
+  {
+    \bool_if:NTF #1
+      {
+        \tex_afterassignment:D \l__xparse_tmpa_tl
+        \cs_set_eq:NN \__xparse_tmp:w
+      }
+      { \l__xparse_tmpa_tl }
+  }
 \cs_new:Npn \__xparse_environment_or_command:
   {
     \bool_if:NTF \l__xparse_environment_bool
@@ -2049,16 +2111,23 @@
     token.~Perhaps~a~backslash~is~missing?
     \c__xparse_ignore_def_tl
   }
-\__kernel_msg_new:nnnn { xparse } { not-single-char }
+\__kernel_msg_new:nnnn { xparse } { not-single-token }
   {
     Argument~delimiter~'#2'~for~the~#1~should~be~
-    a~single~character.
+    a~single~non-space~token.
   }
   {
     The~argument~specification~provided~was~not~valid:~in~a~place~
-    where~a~single~character~is~required,~LaTeX~found~'#2'.
+    where~a~single~token~is~required,~LaTeX~found~'#2'.
     \c__xparse_ignore_def_tl
   }
+\__kernel_msg_new:nnnn { xparse } { forbidden-implicit-group-token }
+  { Argument~delimiter~'#2'~for~the~#1~is~not~allowed. }
+  {
+    The~argument~specification~provided~was~not~valid:~the~implicit~
+    #3-group~token~'#2'~is~not~allowed~as~an~argument~delimiter.
+    \c__xparse_ignore_def_tl
+  }
 \__kernel_msg_new:nnnn { xparse } { processor-in-expandable }
   { Argument~processor~'>{#2}'~cannot~be~used~for~the~expandable~command~'#1'. }
   {

Modified: trunk/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty	2020-03-05 00:53:33 UTC (rev 54098)
+++ trunk/Master/texmf-dist/tex/latex/l3packages/xtemplate/xtemplate.sty	2020-03-05 01:01:48 UTC (rev 54099)
@@ -32,7 +32,7 @@
       }%
     \endinput
   }
-\ProvidesExplPackage{xtemplate}{2020-02-25}{}
+\ProvidesExplPackage{xtemplate}{2020-03-03}{}
   {L3 Experimental prototype document functions}
 \tl_const:Nn \c__xtemplate_code_root_tl      { template~code~>~ }
 \tl_const:Nn \c__xtemplate_defaults_root_tl  { template~defaults~>~ }



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