summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/expl3.dtx9
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3.ins3
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3basics.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3box.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3clist.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3color.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3debug.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx31
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3doc.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3expan.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3file.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3flag.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx282
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx17
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx673
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx184
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp.dtx136
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3int.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3keys.dtx20
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3msg.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3names.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prg.dtx13
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prop.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3quark.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3regex.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3seq.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3skip.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3sort.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3str.dtx6
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3sys.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx1366
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text.dtx41
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx43
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl.dtx10
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3token.dtx78
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx2
61 files changed, 2227 insertions, 801 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
index ea13fbeacf1..09e21e47109 100644
--- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
@@ -24,7 +24,7 @@
%
%<*driver|generic|package|2ekernel>
%</driver|generic|package|2ekernel>
-\def\ExplFileDate{2023-10-10}%
+\def\ExplFileDate{2023-10-23}%
%<*driver>
\documentclass[full]{l3doc}
\usepackage{graphicx}
@@ -51,7 +51,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -311,9 +311,8 @@
% or private.
%
% To allow clear separation of these two cases, the following convention
-% is used. In private functions and variables, two |_| characters are
-% added to the start of the module name. On the other hand, public
-% interfaces to not have these two |_| character. Thus
+% is used. To denote a private function or a private variable (of the module),
+% two |_| characters are used in front of the module name, e.g.
% \begin{verbatim}
% \module_foo:nnn
% \end{verbatim}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3.ins b/Master/texmf-dist/source/latex/l3kernel/l3.ins
index 52c65e4c8e2..24f11d8f7b6 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3.ins
+++ b/Master/texmf-dist/source/latex/l3kernel/l3.ins
@@ -92,6 +92,9 @@ and all files in that bundle must be distributed together.
\from{l3fp-trig.dtx} {package}
\from{l3fp-convert.dtx} {package}
\from{l3fp-random.dtx} {package}
+ \from{l3fp-types.dtx} {package}
+ \from{l3fp-symbolic.dtx}{package}
+ \from{l3fp-functions.dtx}{package}
\from{l3fparray.dtx} {package}
\from{l3cctab.dtx} {package}
\from{l3sort.dtx} {package}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
index 6b484105fe5..00e159d8176 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -1045,7 +1045,7 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}[EXP, added = 2018-06-18]{\use:e}
+% \begin{function}[EXP, added = 2018-06-18, updated = 2023-07-05]{\use:e}
% \begin{syntax}
% \cs{use:e} \Arg{expandable tokens}
% \end{syntax}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
index e300bccc67e..a42f358ae89 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
index dfa6b3c451e..57576531682 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
index 6e455b099c8..567969d5450 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx b/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
index 4192ec029a3..794b53b5f49 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
index 8fc2f6870bd..bd8082cf340 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
index 94824400de0..cf046706b69 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
index 3d225b2d223..2cdf604d02c 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -330,7 +330,7 @@
%
% \subsection{Coloring math mode material}
%
-% Coloring math mode material using \cs{color_select:nn(n)} has some restrictions
+% Coloring math mode material using \cs[no-index]{color_select:nn(n)} has some restrictions
% and often leads to spacing issues and/or poor input syntax. Avoiding generating
% \tn{mathord} atoms whilst coloring only those parts of the input which are
% required needs careful handling. The functionality here covers this important
@@ -341,7 +341,7 @@
% \cs{color_math:nn} \Arg{color expression}\Arg{content}
% \cs{color_math:nnn} \Arg{model(s)} \Arg{value(s)} \Arg{content}
% \end{syntax}
-% Works as for \cs{color_select:n(n)} but applies color only to the math mode
+% Works as for \cs[no-index]{color_select:n(n)} but applies color only to the math mode
% \meta{content}. The function does not generate a group and the \meta{content}
% therefore retains its math atom states. Sub/superscripts are also properly
% handled.
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx b/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
index 8efdc986ccc..c351529d858 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
index c9564f4080a..98d8df40e54 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -549,6 +549,21 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Deprecated \pkg{l3text} functions}
+%
+% \begin{macro}[EXP]{\text_titlecase:n}
+% \begin{macro}[EXP]{\text_titlecase:nn}
+% \begin{macrocode}
+\__kernel_patch_deprecation:nnNNpn { 2023-07-08 } { \text_titlecase_first:n }
+\cs_gset:Npn \text_titlecase:n #1
+ { \text_titlecase_first:n { \text_lowercase:n {#1} } }
+\__kernel_patch_deprecation:nnNNpn { 2023-07-08 } { \text_titlecase_first:nn }
+\cs_gset:Npn \text_titlecase:nn #1#2
+ { \text_titlecase_first:nn {#1} { \text_lowercase:n {#2} } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Deprecated \pkg{l3tl} functions}
%
% \begin{macrocode}
@@ -574,12 +589,12 @@
\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_uppercase:nn }
\cs_gset:Npn \tl_upper_case:nn #1#2
{ \text_uppercase:nn {#1} {#2} }
-\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase_first:n }
\cs_gset:Npn \tl_mixed_case:n #1
- { \text_titlecase:n {#1} }
-\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase:nn }
+ { \text_titlecase_first:n {#1} }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase_first:nn }
\cs_gset:Npn \tl_mixed_case:nn #1#2
- { \text_titlecase:nn {#1} {#2} }
+ { \text_titlecase_first:nn {#1} {#2} }
% \end{macrocode}
% \end{macro}
%
@@ -608,7 +623,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP]{\char_to_nfd:Nm, \char_to_nfd:n}
+% \begin{macro}[EXP]{\char_to_nfd:N, \char_to_nfd:n}
% \begin{macrocode}
\__kernel_patch_deprecation:nnNNpn { 2022-10-09 } { \codepoint_to_nfd:n }
\cs_gset:Npn \char_to_nfd:N #1 { \codepoint_to_nfd:n {`#1} }
@@ -629,8 +644,8 @@
\cs_gset:Npn \char_lower_case:N { \text_lowercase:n }
\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_uppercase:n }
\cs_gset:Npn \char_upper_case:N { \text_uppercase:n }
-\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase:n }
-\cs_gset:Npn \char_mixed_case:N { \text_titlecase:n }
+\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \text_titlecase_first:n }
+\cs_gset:Npn \char_mixed_case:N { \text_titlecase_first:n }
\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_casefold:n }
\cs_gset:Npn \char_fold_case:N { \str_casefold:n }
\__kernel_patch_deprecation:nnNNpn { 2020-01-03 } { \str_lowercase:n }
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
index ed675106ba1..789095d1046 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
@@ -85,7 +85,7 @@ and all files in that bundle must be distributed together.
% require you to do updates, if the class changes.}}
%
% \author{\Team}
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
% \maketitle
% \tableofcontents
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
index df2b7c63abe..59bd089ae65 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
@@ -2,7 +2,7 @@
%
%% File l3dosctrip.dtx
%
-% Copyright (C) 2012,2014-2023 The LaTeX Project
+% Copyright (C) 2012-2023 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -63,7 +63,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
index d4fe6b3a30a..3bf2bd61536 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
index 2d2ae6a183f..af83fe4e088 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
index 637da52ee78..278c71f27c1 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
index da05eafa395..17d75d10459 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
% \maketitle
%
% \begin{documentation}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
index 3db65c9d29f..ccd5e63ac17 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
index 3c5ad9195bf..b79950c2677 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
@@ -2,7 +2,7 @@
%
%% File: l3fp-basics.dtx
%
-% Copyright (C) 2011-2014,2016-2023 The LaTeX Project
+% Copyright (C) 2011-2023 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
index 835f9c43414..70983272ddf 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
index 5ac216bf4c4..f0e691f310b 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
index b83b37335bd..e374e7e2881 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx
new file mode 100644
index 00000000000..a899f3493ae
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-functions.dtx
@@ -0,0 +1,282 @@
+% \iffalse
+%
+%% File l3fp-functions.dtx (C) Copyright 2012-2018,2020,2021,2023 The LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+% https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\usepackage{amsmath}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3fp-functions} package\\ Floating point functions^^A
+% }
+%
+% \author{^^A
+% The \LaTeX{} Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2023-10-23}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-functions} implementation}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Declaring functions}
+%
+% \begin{macro}{\fp_new_function:n}
+% \begin{macro}{\@@_new_function:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_new_function:n #1
+ { \exp_args:No \@@_new_function:n { \tl_to_str:n {#1} } }
+\cs_new_protected:Npn \@@_new_function:n #1
+ {
+ \@@_id_if_invalid:nTF {#1}
+ { \msg_error:nnn { fp } { invalid-identifier } {#1} }
+ {
+ \cs_if_exist:cT { @@_parse_word_#1:N }
+ {
+ \msg_error:nnn
+ { fp } { id-already-defined } {#1}
+ \cs_undefine:c { @@_parse_word_#1:N }
+ \cs_undefine:c { @@_#1_o:w }
+ }
+ \@@_function_set_parsing:Nn \cs_gset_eq:NN {#1}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {\@@_function_set_parsing:Nn, \@@_function_set_parsing_aux:NNn}
+% \begin{macrocode}
+\cs_new:Npn \@@_function_set_parsing:Nn #1#2
+ {
+ \exp_args:NNc \@@_function_set_parsing_aux:NNn #1
+ { @@_parse_word_#2:N } {#2}
+ }
+\cs_new:Npn \@@_function_set_parsing_aux:NNn #1#2#3
+ {
+ \cs_set:Npe \@@_tmp:w
+ {
+ \exp_not:N \@@_parse_function:NNN
+ \exp_not:N \@@_function_o:w
+ \exp_not:c { @@_#3_o:w }
+ }
+ \cs_if_eq:NNF #2 \@@_tmp:w
+ {
+ \cs_if_exist:NTF #2
+ {
+ \msg_warning:nnnn
+ { fp } { id-used-elsewhere } {#3} { function }
+ #1 #2 \@@_tmp:w
+ }
+ {
+ \cs_new_eq:NN #2 \scan_stop: % to declare the function
+ #1 #2 \@@_tmp:w
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_function_o:w}
+% \begin{macrocode}
+\cs_new:Npn \@@_function_o:w #1#2 @
+ {
+ \cs_if_exist:NTF #1
+ { #1 #2 @ }
+ {
+ \exp_after:wN \s_@@_symbolic
+ \exp_after:wN \@@_symbolic_chk:w
+ \exp_after:wN \@@_function_o:w
+ \exp_after:wN #1
+ \exp_after:wN ,
+ \exp_after:wN {
+ \exp:w \exp_end_continue_f:w
+ \@@_exp_after_array_f:w #2 \s_@@_expr_stop
+ \exp_after:wN
+ }
+ \exp_after:wN ;
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Defining functions by their expression}
+%
+% \begin{variable}{\l_@@_function_arg_int}
+% Labels the arguments of a function being defined.
+% \begin{macrocode}
+\int_new:N \l_@@_function_arg_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\fp_set_function:nnn}
+% \begin{macro}{\@@_set_function:Nnnn}
+% \begin{syntax}
+% \cs{fp_set_function:nnn} \Arg{identifier}
+% \Arg{comma-list of variables} \Arg{expression}
+% \end{syntax}
+% Defines the \meta{identifier} to stand for a function which expects
+% some arguments defined by the \meta{comma-list of variables}, and
+% evaluates to the \meta{expression}.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_set_function:nnn #1
+ {
+ \exp_args:NNo \@@_set_function:Nnnn \cs_set_eq:cN
+ { \tl_to_str:n {#1} }
+ }
+\cs_new_protected:Npn \@@_set_function:Nnnn #1#2#3#4
+ {
+ \@@_id_if_invalid:nTF {#2}
+ { \msg_error:nnn { fp } { invalid-identifier } {#2} }
+ {
+ \cs_if_exist:cF { @@_parse_word_#2:N }
+ { \@@_function_set_parsing:Nn \cs_set_eq:NN {#2} }
+ \group_begin:
+ \int_zero:N \l_@@_function_arg_int
+ \exp_args:No \clist_map_inline:nn { \tl_to_str:n {#3} }
+ {
+ \int_incr:N \l_@@_function_arg_int
+ \exp_args:Ne \@@_clear_variable:n
+ { _ \tex_romannumeral:D \l_@@_function_arg_int }
+ \fp_clear_variable:n {##1}
+ \cs_set_nopar:cpe { l_@@_variable_##1_fp }
+ {
+ \exp_not:N \s__fp_symbolic
+ \exp_not:N \@@_symbolic_chk:w
+ \exp_not:N \@@_function_arg_o:w
+ \int_use:N \l_@@_function_arg_int
+ ########1 , { } ;
+ }
+ }
+ \cs_set:Npn \@@_function_arg_o:w ##1 @
+ {
+ \exp_after:wN \s_@@_symbolic
+ \exp_after:wN \@@_symbolic_chk:w
+ \exp_after:wN \@@_function_arg_o:w
+ \tex_romannumeral:D
+ \@@_exp_after_symbolic_loop:N ##1
+ { , \tex_romannumeral:D \use_none:nn }
+ \exp_after:wN \c_zero_int
+ \exp_after:wN { \exp_after:wN } \exp_after:wN ;
+ }
+ \fp_set:Nn \l_@@_symbolic_fp {#4}
+ \use:e
+ {
+ \exp_not:n { \cs_gset:Npn \@@_tmp:w ##1 }
+ { \exp_not:o { \l_@@_symbolic_fp } }
+ }
+ \use:e
+ {
+ \exp_not:n { \cs_gset:Npn \@@_tmp:w ##1 @ }
+ {
+ \exp_not:N \@@_exp_after_symbolic_f:nw
+ \exp_not:n { { \exp_after:wN \exp_stop_f: } }
+ \exp_not:o { \@@_tmp:w { . , {##1} } }
+ }
+ }
+ \group_end:
+ #1 { @@_#2_o:w } \@@_tmp:w
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+% {
+% \@@_function_arg_o:w,
+% \@@_function_arg_few:w,
+% \@@_function_arg_get:w
+% }
+% \begin{macrocode}
+\cs_new:Npn \@@_function_arg_o:w #1. #2
+ {
+ \if_meaning:w @ #2
+ \exp_after:wN \@@_function_arg_few:w
+ \fi:
+ \if_int_compare:w #1 = \c_one_int
+ \exp_after:wN \@@_function_arg_get:w
+ \fi:
+ \@@_use_i_until_s:nw
+ {
+ \exp_after:wN \@@_function_arg_o:w
+ \int_value:w \int_eval:n { #1 - 1 } .
+ }
+ #2
+ }
+\cs_new:Npn \@@_function_arg_few:w #1 @ { \exp_after:wN \c_nan_fp }
+\cs_new:Npn \@@_function_arg_get:w #1#2#3; #4 @
+ {
+ \@@_exp_after_array_f:w #3; \s_@@_expr_stop
+ \exp_after:wN \exp_stop_f:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\fp_clear_function:n}
+% \begin{macro}{\@@_clear_function:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_clear_function:n #1
+ { \exp_args:No \@@_clear_function:n { \tl_to_str:n {#1} } }
+\cs_new_protected:Npn \@@_clear_function:n #1
+ {
+ \cs_undefine:c { @@_parse_word_ #1 :N }
+ \@@_function_set_parsing:Nn \cs_set_eq:NN {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% ^^A todo: add check for number of args
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
index 2f439c2925b..5e98d6b62c2 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -163,7 +163,7 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP]{\@@_compare_back_any:ww, \@@_compare_back:ww, \@@_compare_nan:w}
+% \begin{macro}[EXP]{\@@_compare_back:ww, \@@_bcmp:ww, \@@_compare_back_any:ww, \@@_compare_nan:w}
% \begin{quote}
% \cs{@@_compare_back_any:ww} \meta{y} |;| \meta{x} |;|
% \end{quote}
@@ -178,6 +178,17 @@
% a different type, the highest type is a larger number. Finally, if
% $y\leq 0$, then $x>y$, unless both are zero.
% \begin{macrocode}
+\cs_new:Npn \@@_compare_back:ww #1#2; #3#4;
+ {
+ \cs:w
+ @@
+ \@@_type_from_scan:N #1
+ _bcmp
+ \@@_type_from_scan:N #3
+ :ww
+ \cs_end:
+ #1#2; #3#4;
+ }
\cs_new:Npn \@@_compare_back_any:ww #1#2; #3
{
\@@_if_type_fp:NTwFw
@@ -195,7 +206,7 @@
}
#1#2 ; #3
}
-\cs_new:Npn \@@_compare_back:ww
+\cs_new:Npn \@@_bcmp:ww
\s_@@ \@@_chk:w #1 #2 #3;
\s_@@ \@@_chk:w #4 #5 #6;
{
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
index 418974d8263..58fc4f1f2a2 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
index 3e3b5cfdfc2..3cff0bdc1a1 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
index f0853f59995..901cb5ba340 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx
new file mode 100644
index 00000000000..277ecfabf55
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-symbolic.dtx
@@ -0,0 +1,673 @@
+% \iffalse
+%
+%% File l3fp-symbolic.dtx (C) Copyright 2012-2015,2017,2018,2020,2021,2023 The LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+% https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\usepackage{amsmath}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3fp-symbolic} package\\ Symbolic expressions^^A
+% }
+%
+% \author{^^A
+% The \LaTeX{} Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2023-10-23}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-symbolic} implementation}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Misc}
+%
+% \begin{variable}{\l_@@_symbolic_fp}
+% Scratch floating point.
+% \begin{macrocode}
+\fp_new:N \l_@@_symbolic_fp
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Building blocks for expressions}
+%
+% Every symbolic expression has the form \cs{s_@@_symbolic}
+% \cs{@@_symbolic_chk:w} \meta{operation} |,| \Arg{operands} \meta{junk}
+% |;| where the \meta{operation} is a list of \texttt{N}-type tokens,
+% the \meta{operands} is an array of floating point objects, and the
+% \meta{junk} is to be discarded. If the outermost operator (last to be
+% evaluated) is unary, the expression has the form
+% \begin{quote}
+% \cs{s_@@_symbolic} \cs{@@_symbolic_chk:w} \\
+% \cs{@@_types_unary:NNw} |\__fp_|\meta{op}|_o:w| \meta{token} |,| \\
+% |{| \meta{operand} |}| \meta{junk} |;|
+% \end{quote}
+% where the \meta{op} is a unary operation (|set_sign|, |cos|,
+% \ldots{}), and the \meta{token} and \meta{operand} are used as
+% arguments for \cs{@@_\meta{op}_o:w} (or the type-specific analog of
+% this function). If the outermost operator is binary, the expression
+% has the form
+% \begin{quote}
+% \cs{s_@@_symbolic} \cs{@@_symbolic_chk:w} \\
+% \cs{@@_types_binary:Nww} |\__fp_|\meta{op}|_o:ww| |,| \\
+% |{| \meta{operand_1} \meta{operand_2} |}| \meta{junk} |;|
+% \end{quote}
+% where the \meta{op} is an operation (|+|, |&|, \ldots{}), and
+% |\__fp_|\meta{op}|_o:ww| receives the \meta{operands} as arguments.
+% If the expression consists of a single variable, it is stored as
+% \begin{quote}
+% \cs{s_@@_symbolic} \cs{@@_symbolic_chk:w} \\
+% \cs{@@_variable_o:w} \meta{identifier} |,| \\
+% |{| |}| \meta{junk} |;|
+% \end{quote}
+%
+% Symbolic expressions are stored in a prefix form. When encountering a
+% symbolic expression in a floating point computation, we attempt to
+% evaluate the operands as much as possible, and if that yields floating
+% point numbers rather than expressions, we apply the operator which
+% follows (if the function is known).
+%
+% For instance, the expression |a + b * sin(c)| is stored as
+% \begin{verbatim}
+% \s__fp_symbolic \__fp_symbolic_chk:w
+% \__fp_types_binary:Nww \__fp_+_o:ww ,
+% {
+% \s__fp_symbolic \__fp_symbolic_chk:w
+% \__fp_variable_o:w a , { } ;
+% \s__fp_symbolic \__fp_symbolic_chk:w
+% \__fp_types_binary:Nww \__fp_*_o:ww ,
+% {
+% \s__fp_symbolic \__fp_symbolic_chk:w
+% \__fp_variable_o:w b , { } ;
+% \s__fp_symbolic \__fp_symbolic_chk:w
+% \__fp_types_unary:NNw \__fp_sin_o:w \use_i:nn ,
+% {
+% \s__fp_symbolic \__fp_symbolic_chk:w
+% \__fp_variable_o:w c , { } ;
+% } ;
+% } ;
+% } ;
+% \end{verbatim}
+%
+% \begin{variable}{\s_@@_symbolic}
+% Scan mark indicating the start of a symbolic expression.
+% \begin{macrocode}
+\scan_new:N \s_@@_symbolic
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\@@_symbolic_chk:w}
+% Analog of \cs{@@_chk:w} for symbolic expressions.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_symbolic_chk:w #1,#2#3;
+ {
+ \msg_error:nne { fp } { misused-fp }
+ {
+ \@@_to_tl_dispatch:w
+ \s_@@_symbolic \@@_symbolic_chk:w #1,{#2};
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Expanding after a symbolic expression}
+%
+% \begin{macro}[EXP]
+% {\@@_if_has_symbolic:nTF, \@@_if_has_symbolic_aux:w}
+% Tests if |#1| contains \cs{s_@@_symbolic} at top-level. This test
+% should be precise enough to determine if a given an array contains a
+% symbolic expression or only consists in floating points. Used in
+% \cs{@@_exp_after_symbolic_f:nw}.
+% \begin{macrocode}
+\cs_new:Npn \@@_if_has_symbolic:nTF #1
+ {
+ \@@_if_has_symbolic_aux:w
+ #1 \s_@@_mark \use_i:nn
+ \s_@@_symbolic \s_@@_mark \use_ii:nn
+ \s_@@_stop
+ }
+\cs_new:Npn \@@_if_has_symbolic_aux:w
+ #1 \s_@@_symbolic #2 \s_@@_mark #3#4 \s_@@_stop { #3 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_exp_after_symbolic_f:nw}
+% \begin{macro}[EXP]
+% {\@@_exp_after_symbolic_aux:w, \@@_exp_after_symbolic_loop:N}
+% This function does two things: trigger an \texttt{f}-expansion of
+% the argument~|#1| after the following symbolic expression, and
+% evaluate all pieces of the expression which can be evaluated.
+% \begin{macrocode}
+\cs_new:Npn \@@_exp_after_symbolic_f:nw
+ #1 \s_@@_symbolic \@@_symbolic_chk:w #2, #3#4;
+ {
+ \exp_after:wN \@@_exp_after_symbolic_aux:w
+ \exp:w
+ \@@_exp_after_symbolic_loop:N #2
+ { , \exp:w \use_none:nn }
+ \exp_after:wN \exp_end: \exp_after:wN
+ {
+ \exp:w \exp_end_continue_f:w
+ \@@_exp_after_array_f:w #3 \s_@@_expr_stop
+ \exp_after:wN
+ }
+ \exp_after:wN ;
+ \exp:w \exp_end_continue_f:w #1
+ }
+\cs_new:Npn \@@_exp_after_symbolic_aux:w #1, #2;
+ {
+ \@@_if_has_symbolic:nTF {#2}
+ { \s_@@_symbolic \@@_symbolic_chk:w #1, {#2} ; }
+ { #1 #2 @ \prg_do_nothing: }
+ }
+\cs_new:Npn \@@_exp_after_symbolic_loop:N #1
+ {
+ \exp_after:wN \exp_end:
+ \exp_after:wN #1
+ \exp:w
+ \@@_exp_after_symbolic_loop:N
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Applying infix operators to expressions}
+%
+% \begin{macro}[EXP]{\@@_symbolic_binary_o:Nww}
+% Used when applying infix operators to expressions.
+% \begin{macrocode}
+\cs_new:Npn \@@_symbolic_binary_o:Nww #1 #2; #3;
+ {
+ \@@_exp_after_symbolic_f:nw { \exp_after:wN \exp_stop_f: }
+ \s_@@_symbolic \@@_symbolic_chk:w
+ \@@_types_binary:Nww #1 , { #2; #3; } ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{@makeother}{^} %^^A Hack!
+% \begin{@makeother}{|} %^^A Hack!
+% \begin{@makeother}{&} %^^A Hack!
+% \begin{macro}[EXP]
+% {
+% \@@_symbolic_+_symbolic_o:ww,
+% \@@_symbolic_+_o:ww,
+% \@@_+_symbolic_o:ww,
+% \@@_symbolic_-_symbolic_o:ww,
+% \@@_symbolic_-_o:ww,
+% \@@_-_symbolic_o:ww,
+% \@@_symbolic_*_symbolic_o:ww,
+% \@@_symbolic_*_o:ww,
+% \@@_*_symbolic_o:ww,
+% \@@_symbolic_/_symbolic_o:ww,
+% \@@_symbolic_/_o:ww,
+% \@@_/_symbolic_o:ww,
+% \@@_symbolic_^_symbolic_o:ww,
+% \@@_symbolic_^_o:ww,
+% \@@_^_symbolic_o:ww,
+% \@@_symbolic_|_symbolic_o:ww,
+% \@@_symbolic_|_o:ww,
+% \@@_|_symbolic_o:ww,
+% \@@_symbolic_&_symbolic_o:ww,
+% \@@_symbolic_&_o:ww,
+% \@@_&_symbolic_o:ww,
+% }
+% \begin{macrocode}
+\cs_set:Npn \@@_tmp:w #1#2
+ {
+ \cs_new_nopar:cpn
+ { @@_symbolic_#2_symbolic_o:ww }
+ { \@@_symbolic_binary_o:Nww #1 }
+ \cs_new_eq:cc
+ { @@_symbolic_#2 _o:ww }
+ { @@_symbolic_#2_symbolic_o:ww }
+ \cs_new_eq:cc
+ { @@ _#2_symbolic_o:ww }
+ { @@_symbolic_#2_symbolic_o:ww }
+ }
+\tl_map_inline:nn { + - * / ^ & | }
+ { \exp_args:Nc \@@_tmp:w { @@_#1_o:ww } {#1} }
+% \end{macrocode}
+% \end{macro}
+% \end{@makeother}
+% \end{@makeother}
+% \end{@makeother}
+%
+% \subsection{Applying prefix functions to expressions}
+%
+% \begin{macro}[aux, EXP]{\@@_symbolic_unary_o:NNw}
+% Used when applying infix operators to expressions.
+% \begin{macrocode}
+\cs_new:Npn \@@_symbolic_unary_o:NNw #1#2#3; @
+ {
+ \@@_exp_after_symbolic_f:nw { \exp_after:wN \exp_stop_f: }
+ \s_@@_symbolic \@@_symbolic_chk:w
+ \@@_types_unary:NNw #1#2 , { #3; } ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+% {
+% \@@_symbolic_acos_o:w ,
+% \@@_symbolic_acsc_o:w ,
+% \@@_symbolic_asec_o:w ,
+% \@@_symbolic_asin_o:w ,
+% \@@_symbolic_cos_o:w ,
+% \@@_symbolic_cot_o:w ,
+% \@@_symbolic_csc_o:w ,
+% \@@_symbolic_exp_o:w ,
+% \@@_symbolic_ln_o:w ,
+% \@@_symbolic_not_o:w ,
+% \@@_symbolic_sec_o:w ,
+% \@@_symbolic_set_sign_o:w ,
+% \@@_symbolic_sin_o:w ,
+% \@@_symbolic_tan_o:w ,
+% }
+% \begin{macrocode}
+\tl_map_inline:nn
+ {
+ {acos} {acsc} {asec} {asin} {cos} {cot} {csc} {exp} {ln}
+ {not} {sec} {set_sign} {sin} {sqrt} {tan}
+ }
+ {
+ \cs_new_nopar:cpe { @@_symbolic_#1_o:w }
+ {
+ \exp_not:N \@@_symbolic_unary_o:NNw
+ \exp_not:c { @@_#1_o:w }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Conversions}
+%
+% \begin{macro}[EXP]
+% {
+% \@@_symbolic_to_decimal:w,
+% \@@_symbolic_to_int:w,
+% \@@_symbolic_to_scientific:w
+% }
+% \begin{macro}[EXP]{\@@_symbolic_convert:wnnN}
+% Symbolic expressions cannot be converted to decimal, integer, or
+% scientific notation unless they can be reduced to
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1#2#3
+ {
+ \cs_new_nopar:cpn { @@_symbolic_to_#1:w }
+ {
+ \exp_after:wN \@@_symbolic_convert:wnnN
+ \exp:w \exp_end_continue_f:w
+ \@@_exp_after_symbolic_f:nw { { #2 } { fp_to_#1 } #3 }
+ }
+ }
+\@@_tmp:w { decimal } { 0 } \@@_to_decimal_dispatch:w
+\@@_tmp:w { int } { 0 } \@@_to_int_dispatch:w
+\@@_tmp:w { scientific } { nan } \@@_to_scientific_dispatch:w
+\cs_new:Npn \@@_symbolic_convert:wnnN #1#2; #3#4#5
+ {
+ \str_if_eq:nnTF {#1} { \s_@@_symbolic }
+ { \@@_invalid_operation:nnw {#3} {#4} #1#2; }
+ { #5 #1#2; }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+% {\@@_symbolic_cs_arg_to_fn:NN, \@@_symbolic_op_arg_to_fn:nN}
+% \begin{macrocode}
+\cs_new:Npn \@@_symbolic_cs_arg_to_fn:NN #1
+ {
+ \exp_args:Nf \@@_symbolic_op_arg_to_fn:nN
+ { \@@_types_cs_to_op:N #1 }
+ }
+\cs_new:Npn \@@_symbolic_op_arg_to_fn:nN #1#2
+ {
+ \str_case:nnF { #1 #2 }
+ {
+ { not ? } { ! }
+ { set_sign 0 } { abs }
+ { set_sign 2 } { - }
+ }
+ {
+ \token_if_eq_meaning:NNTF #2 \use_ii:nn
+ { #1 d } {#1}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_symbolic_to_tl:w}
+% \begin{macro}[rEXP]
+% {
+% \@@_symbolic_unary_to_tl:NNw,
+% \@@_symbolic_binary_to_tl:Nww
+% }
+% Converting a symbolic expression to a token list is possible.
+% \begin{macrocode}
+\cs_new:Npn \@@_symbolic_to_tl:w
+ \s_@@_symbolic \@@_symbolic_chk:w #1#2, #3#4;
+ {
+ \str_case:nnTF {#1}
+ {
+ { \@@_types_unary:NNw } { \@@_symbolic_unary_to_tl:NNw }
+ { \@@_types_binary:Nww } { \@@_symbolic_binary_to_tl:Nww }
+ { \@@_function_o:w } { \@@_symbolic_function_to_tl:Nw }
+ }
+ { #2, #3 @ }
+ { \tl_to_str:n {#2} }
+ }
+\cs_new:Npn \@@_symbolic_unary_to_tl:NNw #1#2 , #3 @
+ {
+ \use:e
+ {
+ \@@_symbolic_cs_arg_to_fn:NN #1#2
+ ( \@@_to_tl_dispatch:w #3 )
+ }
+ }
+\cs_new:Npn \@@_symbolic_binary_to_tl:Nww #1, #2; #3; @
+ {
+ \use:e
+ {
+ ( \@@_to_tl_dispatch:w #2; )
+ \@@_types_cs_to_op:N #1
+ ( \@@_to_tl_dispatch:w #3; )
+ }
+ }
+\cs_new:Npn \@@_symbolic_function_to_tl:Nw #1, #2@
+ {
+ \use:e
+ {
+ \@@_types_cs_to_op:N #1
+ ( \@@_array_to_clist:n {#2} )
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Identifiers}
+%
+% Functions defined here are not necessarily tied to symbolic
+% expressions.
+%
+% \begin{macro}[TF]{\@@_id_if_invalid:n}
+% \begin{macro}[EXP]{\@@_id_if_invalid_aux:N}
+% If |#1| contains a space, it is not a valid identifier. Otherwise,
+% loop through letters in |#1|: if it is not a letter, break the loop
+% and return \texttt{true}. If the end of the loop is reached
+% without finding any non-letter, return \texttt{false}.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn
+ \@@_id_if_invalid:n #1 { T , F , TF }
+ {
+ \tl_if_empty:nTF {#1}
+ { \prg_return_true: }
+ {
+ \tl_if_in:onTF { \tl_to_str:n {#1} } { ~ }
+ { \prg_return_true: }
+ {
+ \exp_after:wN \@@_id_if_invalid_aux:N \tl_to_str:n {#1}
+ { ? \prg_break:n \prg_return_false: }
+ \prg_break_point:
+ }
+ }
+ }
+\cs_new:Npn \@@_id_if_invalid_aux:N #1
+ {
+ \use_none:n #1
+ \int_compare:nF { `a <= `#1 <= `z }
+ {
+ \int_compare:nF { `A <= `#1 <= `Z }
+ { \prg_break:n \prg_return_true: }
+ }
+ \@@_id_if_invalid_aux:N
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Declaring variables and assigning values}
+%
+% \begin{macro}[EXP]{\@@_variable_o:w}
+% We do not use \cs{exp_last_unbraced:Nv} to extract the value of
+% |\l__fp_variable_#1_fp| because in \cs{fp_set_variable:nn} we define
+% this \texttt{fp} variable to be something which \texttt{f}-expands
+% to an actual floating point, rather than a genuine floating point.
+% \begin{macrocode}
+\cs_new:Npn \@@_variable_o:w #1 @ #2
+ {
+ \fp_if_exist:cTF { l_@@_variable_#1_fp }
+ {
+ \exp_last_unbraced:Nf \@@_exp_after_array_f:w
+ { \use:c { l_@@_variable_#1_fp } } \s_@@_expr_stop
+ \exp_after:wN \exp_stop_f: #2
+ }
+ {
+ \token_if_eq_meaning:NNTF #2 \prg_do_nothing:
+ {
+ \s_@@_symbolic \@@_symbolic_chk:w
+ \@@_variable_o:w #1 , { } ;
+ }
+ {
+ \exp_after:wN \s_@@_symbolic
+ \exp_after:wN \@@_symbolic_chk:w
+ \exp_after:wN \@@_variable_o:w
+ \exp:w
+ \@@_exp_after_symbolic_loop:N #1
+ { , \exp:w \use_none:nn }
+ \exp_after:wN \exp_end:
+ \exp_after:wN { \exp_after:wN } \exp_after:wN ;
+ #2
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {\@@_variable_set_parsing:Nn, \@@_variable_set_parsing_aux:NNn}
+% \begin{macrocode}
+\cs_new:Npn \@@_variable_set_parsing:Nn #1#2
+ {
+ \cs_set_nopar:Npn \@@_tmp:w
+ {
+ \@@_exp_after_symbolic_f:nw { \@@_parse_infix:NN }
+ \s_@@_symbolic \@@_symbolic_chk:w
+ \@@_variable_o:w #2 , { } ;
+ }
+ \exp_args:NNc \@@_variable_set_parsing_aux:NNn #1
+ { @@_parse_word_#2:N } {#2}
+ }
+\cs_new:Npn \@@_variable_set_parsing_aux:NNn #1#2#3
+ {
+ \cs_if_eq:NNF #2 \@@_tmp:w
+ {
+ \cs_if_exist:NTF #2
+ {
+ \msg_warning:nnnn
+ { fp } { id-used-elsewhere } {#3} { variable }
+ #1 #2 \@@_tmp:w
+ }
+ {
+ \cs_new_eq:NN #2 \scan_stop: % to declare the function
+ #1 #2 \@@_tmp:w
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\fp_clear_variable:n}
+% \begin{macro}{\@@_clear_variable:n}
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_clear_variable:n #1
+ {
+ \@@_id_if_invalid:nTF {#1}
+ { \msg_error:nnn { fp } { id-invalid } {#1} }
+ { \exp_args:No \@@_clear_variable:n { \tl_to_str:n {#1} } }
+ }
+\cs_new_protected:Npn \@@_clear_variable:n #1
+ {
+ \cs_undefine:c { l_@@_variable_#1_fp }
+ \@@_variable_set_parsing:Nn \cs_set_eq:NN {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\fp_new_variable:n}
+% \begin{macro}{\@@_new_variable:n}
+% Check that |#1| is a valid identifier. If the identifier is already
+% in use, complain. Then set |\__fp_parse_word_#1:N| to use
+% |\__fp_variable_o:w|.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_new_variable:n #1
+ {
+ \@@_id_if_invalid:nTF {#1}
+ { \msg_error:nnn { fp } { id-invalid } {#1} }
+ { \exp_args:No \@@_new_variable:n { \tl_to_str:n {#1} } }
+ }
+\cs_new_protected:Npn \@@_new_variable:n #1
+ {
+ \cs_if_exist:cT { @@_parse_word_#1:N }
+ {
+ \msg_error:nnn
+ { fp } { id-already-defined } {#1}
+ \cs_undefine:c { @@_parse_word_#1:N }
+ \cs_undefine:c { l_@@_variable_#1_fp }
+ }
+ \@@_variable_set_parsing:Nn \cs_gset_eq:NN {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\fp_set_variable:nn}
+% \begin{macro}{\@@_set_variable:nn}
+% Refuse invalid identifiers. If the variable does not exist yet,
+% define it just as in \cs{fp_new_variable:n} (but without unnecessary
+% checks). Then evaluate~|#2|. If the result contains the
+% identifier~|#1|, we would later get a loop in cases such as
+% \begin{quote}
+% \cs{fp_set_variable:nn} |{A}| |{A}|\\
+% \cs{fp_show:n} |{A}|
+% \end{quote}
+% To detect this, define |\l__fp_variable_#1_fp| to raise an
+% internal flag and evaluate to \texttt{nan}. Then re-evaluate
+% \cs{l_@@_symbolic_fp}, and store the result in~|#1|. If the flag is
+% raised, |#1|~was present in \cs{l_@@_symbolic_fp}. In all cases,
+% the |#1|-free result ends up in |\l__fp_variable_#1_fp|.
+% \begin{macrocode}
+\flag_new:n { @@_symbolic }
+\cs_new_protected:Npn \fp_set_variable:nn #1
+ {
+ \@@_id_if_invalid:nTF {#1}
+ { \msg_error:nnn { fp } { id-invalid } {#1} }
+ { \exp_args:No \@@_set_variable:nn { \tl_to_str:n {#1} } }
+ }
+\cs_new_protected:Npn \@@_set_variable:nn #1#2
+ {
+ \@@_variable_set_parsing:Nn \cs_set_eq:NN {#1}
+ \fp_set:Nn \l_@@_symbolic_fp {#2}
+ \cs_set_nopar:cpn { l_@@_variable_#1_fp }
+ { \flag_ensure_raised:n { @@_symbolic } \c_nan_fp }
+ \flag_clear:n { @@_symbolic }
+ \fp_set:cn { l_@@_variable_#1_fp } { \l_@@_symbolic_fp }
+ \flag_if_raised:nT { @@_symbolic }
+ {
+ \msg_error:nneee { fp } { id-loop }
+ { \tl_to_str:n {#1} }
+ { \tl_to_str:n {#2} }
+ { \fp_to_tl:N \l_@@_symbolic_fp }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% \begin{macrocode}
+\msg_new:nnnn { fp } { id-invalid }
+ { Floating~point~identifier~'#1'~invalid. }
+ {
+ LaTeX~has~been~asked~to~create~a~new~floating~point~identifier~'#1'~
+ but~this~may~only~contain~ASCII~letters.
+ }
+\msg_new:nnnn { fp } { id-already-defined }
+ { Floating~point~identifier~'#1'~already~defined. }
+ {
+ LaTeX~has~been~asked~to~create~a~new~floating~point~identifier~'#1'~
+ but~this~name~has~already~been~used~elsewhere.
+ }
+\msg_new:nnnn { fp } { id-used-elsewhere }
+ { Floating~point~identifier~'#1'~already~used~for~something~else. }
+ {
+ LaTeX~has~been~asked~to~create~a~new~floating~point~identifier~'#1'~
+ but~this~name~is~used,~and~is~not~a~user-defined~#2.
+ }
+\msg_new:nnnn { fp } { id-loop }
+ { Variable~'#1'~used~in~the~definition~of~'#1'. }
+ {
+ LaTeX~has~been~asked~to~set~the~floating~point~identifier~'#1'~
+ to~the~expression~'#2'.~Evaluating~this~expression~yields~'#3',~
+ which~contains~'#1'~itself.
+ }
+% \end{macrocode}
+%
+% \subsection{Road-map}
+%
+% The following functions are not implemented: |min|, |max|, |?:|,
+% comparisons, |round|, |atan|, |acot|.
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
index 674ecdfd2db..1bdece9ba76 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
@@ -2,7 +2,7 @@
%
%% File: l3fp-traps.dtx
%
-% Copyright (C) 2011-2014,2016-2023 The LaTeX Project
+% Copyright (C) 2011-2023 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
% \maketitle
%
% \begin{documentation}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
index b7bc6c19cec..c49383a1787 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx
new file mode 100644
index 00000000000..693cec5cccf
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-types.dtx
@@ -0,0 +1,184 @@
+% \iffalse
+%
+%% File l3fp-types.dtx (C) Copyright 2012-2015,2017,2018,2020,2021,2023 The LaTeX Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version. The latest version
+% of this license is in the file
+%
+% http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3kernel bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+% https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\usepackage{amsmath}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3fp-types} package\\ Floating point types^^A
+% }
+%
+% \author{^^A
+% The \LaTeX{} Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released 2023-10-23}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-types} implementation}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Support for types}
+%
+% Despite lack of documentation, the \pkg{l3fp} internals support types.
+% Each additional type must define
+% \begin{itemize}
+% \item |\s__fp_|\meta{type} and |\__fp_|\meta{type}|_chk:w|;
+% \item |\__fp_exp_after_|\meta{type}|_f:nw|;
+% \item |\__fp_|\meta{type}|_to_|\meta{out}|:w| for \meta{out} among
+% |decimal|, |scientific|, |tl|;
+% \end{itemize}
+% and may define
+% \begin{itemize}
+% \item |\__fp_|\meta{type}|_to_int:w| and |\__fp_|\meta{type}|_to_dim:w|;
+% \item |\__fp_|\meta{op}|_|\meta{type}|_o:w| for any of the \meta{op}
+% that the type implements, among |acos|, |acsc|, |asec|, |asin|,
+% |cos|, |cot|, |csc|, |exp|, |ln|, |not|, |sec|, |set_sign|, |sin|,
+% |tan|;
+% \item |\__fp_|\meta{type_1}|_|\meta{op}|_|\meta{type_2}|_o:ww| for
+% \meta{op} among |^*/-+&|\verb"|" and for every pair of types;
+% \item |\__fp_|\meta{type_1}|_bcmp_|\meta{type_2}|:ww| for every
+% pair of types.
+% \end{itemize}
+% The latter is set up in \pkg{l3fp-logic}.
+%
+% \subsection{Dispatch according to the type}
+%
+% \begin{macro}[EXP]
+% {\@@_types_cs_to_op:N, \@@_types_cs_to_op_auxi:wwwn}
+% From |\__fp_|\meta{op}|_o:w| produce \meta{op}, otherwise~|?|.
+% \begin{macrocode}
+\cs_new:Npe \@@_types_cs_to_op:N #1
+ {
+ \exp_not:N \exp_after:wN \exp_not:N \@@_types_cs_to_op_auxi:wwwn
+ \exp_not:N \token_to_str:N #1 \s_@@_mark
+ \exp_not:N \@@_use_i_delimit_by_s_stop:nw
+ \tl_to_str:n { @@_ _o:w } \s_@@_mark
+ { \exp_not:N \@@_use_i_delimit_by_s_stop:nw ? }
+ \s_@@_stop
+ }
+\use:e
+ {
+ \cs_new:Npn \exp_not:N \@@_types_cs_to_op_auxi:wwwn
+ #1 \tl_to_str:n { @@_ } #2
+ \tl_to_str:n { _o:w } #3 \s_@@_mark #4 { #4 {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_types_unary:NNw}
+% \begin{macro}[EXP]
+% {\@@_types_unary_auxi:nNw, \@@_types_unary_auxii:NnNw}
+% \begin{syntax}
+% \cs{@@_types_unary:NNw} |\__fp_|\meta{function}|_o:w|
+% ~~\meta{token} \meta{operand} |@|
+% \end{syntax}
+% \begin{macrocode}
+\cs_new:Npn \@@_types_unary:NNw #1
+ {
+ \exp_args:Nf \@@_types_unary_auxi:nNw
+ { \@@_types_cs_to_op:N #1 }
+ }
+\cs_new:Npn \@@_types_unary_auxi:nNw #1#2#3
+ {
+ \exp_after:wN \@@_types_unary_auxii:NnNw
+ \cs:w @@_#1 \@@_type_from_scan:N #3 _o:w \cs_end:
+ {#1}
+ #2#3
+ }
+\cs_new:Npn \@@_types_unary_auxii:NnNw #1#2#3
+ {
+ \token_if_eq_meaning:NNTF \scan_stop: #1
+ { \@@_invalid_operation_o:nw {#2} }
+ { #1 #3 }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_types_binary:Nww}
+% \begin{macro}[EXP]
+% {\@@_types_binary_auxi:Nww, \@@_types_binary_auxii:NNww}
+% \begin{syntax}
+% \cs{@@_types_binary:Nww} |\__fp_|\meta{binop}|_o:ww|
+% ~~\meta{operand_1} \meta{operand_2} |@|
+% \end{syntax}
+% \begin{macrocode}
+\cs_new:Npn \@@_types_binary:Nww #1
+ {
+ \exp_last_unbraced:Nf \@@_types_binary_auxi:Nww
+ { \@@_types_cs_to_op:N #1 }
+ }
+\cs_new:Npn \@@_types_binary_auxi:Nww #1#2#3; #4#5; @
+ {
+ \exp_after:wN \@@_types_binary_auxii:NNww
+ \cs:w
+ @@
+ \@@_type_from_scan:N #2
+ _#1
+ \@@_type_from_scan:N #4
+ _o:ww
+ \cs_end:
+ #1 #2#3; #4#5;
+ }
+\cs_new:Npn \@@_types_binary_auxii:NNww #1#2
+ {
+ \token_if_eq_meaning:NNTF \scan_stop: #1
+ { \@@_invalid_operation_o:Nww #2 }
+ {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
index 60a7b7534fd..578d568978f 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
@@ -49,7 +49,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -658,6 +658,138 @@
% the \meta{code} should make use of the \meta{tl~var}.
% \end{function}
%
+% \section{Symbolic expressions}
+%
+% Floating point expressions support variables: these can only be set locally,
+% so act like standard \cs[no-index]{l_\dots} variables.
+% \begin{quote}\let\obeyedline=\newline\obeylines^^A
+% \cs{fp_new_variable:n} |{ A }|
+% \cs{fp_set:Nn} \cs{l_tmpb_fp} |{ 1 * sin(A) + 3**2 }|
+% \cs{fp_show:n} |{| \cs{l_tmpb_fp} |}|
+% \cs{fp_show:N} \cs{l_tmpb_fp}
+% \cs{fp_set_variable:nn} |{ A }| |{ pi/2 }|
+% \cs{fp_show:n} |{| \cs{l_tmpb_fp} |}|
+% \cs{fp_show:N} \cs{l_tmpb_fp}
+% \cs{fp_set_variable:nn} |{ A }| |{ 0 }|
+% \cs{fp_show:n} |{| \cs{l_tmpb_fp} |}|
+% \cs{fp_show:N} \cs{l_tmpb_fp}
+% \end{quote}
+% defines~|A| to be a variable, then defines \cs{l_tmpb_fp} to stand for
+% |1*sin(A)+9| (note that |3**2| is evaluated, but the |1*|~product is
+% not simplified away). Until \cs{l_tmpb_fp} is changed, \cs{fp_show:N}
+% \cs{l_tmpb_fp} will show |((1*sin(A))+9)| regardless of the value
+% of~|A|. The next step defines~|A| to be equal to~|pi/2|: then
+% \cs{fp_show:n} |{| \cs{l_tmpb_fp} |}| will evaluate \cs{l_tmpb_fp} and
+% show~|10|. We then redefine~|A| to be~|0|: since \cs{l_tmpb_fp} still
+% stands for |1*sin(A)+9|, the value shown is then~|9|. Variables can
+% be set with \cs{fp_set_variable:nn} to arbitrary floating point
+% expressions including other variables.
+%
+% \begin{function}[added = 2023-10-19]{\fp_new_variable:n}
+% \begin{syntax}
+% \cs{fp_new_variable:n} \Arg{identifier}
+% \end{syntax}
+% Declares the \meta{identifier} as a variable, which allows it to be
+% used in floating point expressions. For instance,
+% \begin{quote}
+% \cs{fp_new_variable:n} |{ A }| \\
+% \cs{fp_show:n} |{ A**2 - A + 1 }|
+% \end{quote}
+% shows |(((A^2)-A)+1)|. If the declaration was missing, the parser
+% would complain about an \enquote{\texttt{Unknown fp word 'A'}}. The
+% \meta{identifier} must consist entirely of Latin letters among
+% |[a-zA-Z]|.
+% \end{function}
+%
+% \begin{function}[added = 2023-10-19]{\fp_set_variable:nn}
+% \begin{syntax}
+% \cs{fp_set_variable:nn} \Arg{identifier} \Arg{fp expr}
+% \end{syntax}
+% Defines the \meta{identifier} to stand in any further expression for
+% the result of evaluating the \meta{floating point expression} as
+% much as possible. The result may contain other variables, which are
+% then replaced by their values if they have any. For instance,
+% \begin{quote}\let\obeyedline=\newline\obeylines^^A
+% \cs{fp_new_variable:n} |{ A }|
+% \cs{fp_new_variable:n} |{ B }|
+% \cs{fp_new_variable:n} |{ C }|
+% \cs{fp_set_variable:nn} |{ A } { 3 }|
+% \cs{fp_set_variable:nn} |{ C } { A ** 2 + B * 1 }|
+% \cs{fp_show:n} |{ C + 4 }|
+% \cs{fp_set_variable:nn} |{ A } { 4 }|
+% \cs{fp_show:n} |{ C + 4 }|
+% \end{quote}
+% shows |((9+(B*1))+4)| twice: changing the value of~|A| to~|4| does
+% not alter~|C| because |A|~was replaced by its value~|3| when
+% evaluating |A**2+B*1|.
+% \end{function}
+%
+% \begin{function}[added = 2023-10-19]{\fp_clear_variable:n}
+% \begin{syntax}
+% \cs{fp_clear_variable:n} \Arg{identifier}
+% \end{syntax}
+% Removes any value given by \cs{fp_set_variable:nn} to the variable
+% with this \meta{identifier}. For instance,
+% \begin{quote}\let\obeyedline=\newline\obeylines^^A
+% \cs{fp_new_variable:n} |{ A }|
+% \cs{fp_set_variable:nn} |{ A } { 3 }|
+% \cs{fp_show:n} |{ A ^ 2 }|
+% \cs{fp_clear_variable:n} |{ A }|
+% \cs{fp_show:n} |{ A ^ 2 }|
+% \end{quote}
+% shows~|9|, then~|(A^2)|.
+% \end{function}
+%
+% \section{User-defined functions}
+%
+% It is possible to define new user functions which can be used inside
+% the argument to \cs{fp_eval:n}, etc. These functions may take one or
+% more named arguments, and should be implemented using expansion methods
+% only.
+%
+% \begin{function}[added = 2023-10-19]{\fp_new_function:n}
+% \begin{syntax}
+% \cs{fp_new_function:n} \Arg{identifier}
+% \end{syntax}
+% Declares the \meta{identifier} as a function, which allows it to be
+% used in floating point expressions. For instance,
+% \begin{quote}
+% \cs{fp_new_function:n} |{ foo }| \\
+% \cs{fp_show:n} |{ foo ( 1 + 2 , foo(3), A ) ** 2 } }|
+% \end{quote}
+% shows |(foo(3, foo(3), A))^(2)|. If the declaration was missing,
+% the parser would complain about an \enquote{\texttt{Unknown fp word 'foo'}}.
+% The \meta{identifier} must consist entirely of Latin letters |[a-zA-Z]|.
+% \end{function}
+%
+% \begin{function}[added = 2023-10-19]{\fp_set_function:nnn}
+% \begin{syntax}
+% \cs{fp_set_function:nnn} \Arg{identifier} \Arg{vars} \Arg{fp expr}
+% \end{syntax}
+% Defines the \meta{identifier} to stand in any further expression for
+% the result of evaluating the \meta{floating point expression}, with
+% the \meta{identifier} accepting the \meta{vars} (a comma list).
+% The result may contain other functions, which are
+% then replaced by their results if they have any. For instance,
+% \begin{quote}
+% \cs{fp_new_function:n} |{ foo }| \\
+% \cs{fp_set_function:nnn} |{ npow } { a,b } { a**b }| \\
+% \cs{fp_show:n} |{ npow(16,0.25) } }|
+% \end{quote}
+% shows |2|. The names of the \meta{vars} must
+% consist entirely of Latin letters |[a-zA-Z]|, but are otherwise not
+% restricted: in particular, they are independent of any variables
+% declared by \cs{fp_new_variable:n}.
+% \end{function}
+%
+% \begin{function}[added = 2023-10-19]{\fp_clear_function:n}
+% \begin{syntax}
+% \cs{fp_clear_function:n} \Arg{identifier}
+% \end{syntax}
+% Removes any definition given by \cs{fp_set_function:nnn} to the function
+% with this \meta{identifier}.
+% \end{function}
+%
% \section{Some useful constants, and scratch variables}
%
% \begin{variable}[added = 2012-05-08, module = fp]{\c_zero_fp, \c_minus_zero_fp}
@@ -1417,7 +1549,7 @@
% \begin{function}[EXP, added = 2012-09-26, tested = m3fp-convert003]
% {\fp_max:nn, \fp_min:nn}
% \begin{syntax}
-% \cs{fp_max:nn} \Arg{fp expression 1} \Arg{fp expression 2}
+% \cs{fp_max:nn} \Arg{fp expr_1} \Arg{fp expr_2}
% \end{syntax}
% Evaluates the \meta{fp exprs} as described for
% \cs{fp_eval:n} and leaves the resulting larger (\texttt{max}) or
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
index 9929135baa5..36d84a593dc 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
index e012e191d21..c1dc697e718 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -94,7 +94,7 @@
% \int_show:n { \l_my_tl + \l_my_int * 3 - ( 3 + 4 * 5 ) }
% \end{verbatim}
% show the same result $-6$ because \cs[no-index]{l_my_tl} expands to
-% the integer denotation~|5| while the integer variable \cs{l_my_int}
+% the integer denotation~|5| while the integer variable \cs[no-index]{l_my_int}
% takes the value~$4$. As the \meta{integer expression} is fully
% expanded from left to right during evaluation, fully expandable and
% restricted-expandable functions can both be used, and \cs{exp_not:n}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
index 10458ad602f..cbfdc48666c 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx b/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
index d517f72a228..ce3ab209700 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
index 95ddcd0a383..9fea120c910 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -385,10 +385,10 @@
% \begin{syntax}
% \meta{key} .legacy_if_set:n = \meta{switch}
% \end{syntax}
-% Defines \meta{key} to set legacy \cs{if} \meta{switch} to \meta{value}
+% Defines \meta{key} to set legacy \cs[no-index]{if\meta{switch}} to \meta{value}
% (which must be either \enquote{\texttt{true}} or \enquote{\texttt{false}}).
% The \meta{switch} is the name of the switch \emph{without the leading
-% \cs{if}}.
+% \texttt{if}}.
%
% The \texttt{inverse} versions will set the \meta{switch} to the logical
% opposite of the \meta{value}.
@@ -740,16 +740,12 @@
% \end{function}
%
% \begin{variable}[updated = 2020-02-08]
-% {\l_keys_key_str, \l_keys_path_str, \l_keys_value_tl}
+% {\l_keys_path_str, \l_keys_key_str, \l_keys_value_tl}
% For each key processed, information of the full \emph{path} of the
% key, the \emph{name} of the key and the \emph{value} of the key is
% available within two string and one token list variables.
% These may be used within the code of the key.
%
-% The \emph{value} is everything after the \texttt{=}, which may be
-% empty if no value was given. This is stored in \cs{l_keys_value_tl}, and
-% is not processed in any way by \cs{keys_set:nn}.
-%
% The \emph{path} of the key is a \enquote{full} description of the key,
% and is unique for each key. It consists of the module and full key name,
% thus for example
@@ -767,6 +763,10 @@
% \texttt{/}, and thus is not unique. In the preceding examples, both keys
% have name \texttt{key-a} despite having different paths. This information
% is stored in \cs{l_keys_key_str}.
+%
+% The \emph{value} is everything after the \texttt{=}, which may be
+% empty if no value was given. This is stored in \cs{l_keys_value_tl}, and
+% is not processed in any way by \cs{keys_set:nn}.
% \end{variable}
%
% \section{Handling of unknown keys}
@@ -788,10 +788,10 @@
% {
% \keys_set_known:nn, \keys_set_known:nV,
% \keys_set_known:nv, \keys_set_known:ne,
-% \keys_set_known:no
+% \keys_set_known:no,
% \keys_set_known:nnN, \keys_set_known:nVN,
% \keys_set_known:nvN, \keys_set_known:neN,
-% \keys_set_known:noN
+% \keys_set_known:noN,
% \keys_set_known:nnnN, \keys_set_known:nVnN,
% \keys_set_known:nvnN, \keys_set_known:nenN,
% \keys_set_known:nonN
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx b/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
index 92b8cdb971f..78adefa2dae 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -60,7 +60,7 @@
% \cs{legacy_if:nTF} \Arg{name} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the \LaTeXe{}/plain \TeX{} conditional (generated by \tn{newif})
-% if \texttt{true} or \texttt{false} and branches accordingly. The
+% is \texttt{true} or \texttt{false} and branches accordingly. The
% \meta{name} of the conditional should \emph{omit} the leading \texttt{if}.
% \end{function}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
index c7832c892df..c0ec4f69a04 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
index 4feb4115a10..382aab68ddd 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
index f299b215791..e85262831f2 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx b/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
index f583b393ca4..9c6172caafc 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
index e3f09d90d31..c676e7343e6 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -581,7 +581,7 @@
% \begin{syntax}
% \cs{bool_until_do:Nn} \meta{boolean} \Arg{code}
% \end{syntax}
-% This function firsts checks the logical value of the \meta{boolean}.
+% This function first checks the logical value of the \meta{boolean}.
% If it is \texttt{false} the \meta{code} is placed in the input stream
% and expanded. After the completion of the \meta{code} the truth
% of the \meta{boolean} is re-evaluated. The process then loops
@@ -592,7 +592,7 @@
% \begin{syntax}
% \cs{bool_while_do:Nn} \meta{boolean} \Arg{code}
% \end{syntax}
-% This function firsts checks the logical value of the \meta{boolean}.
+% This function first checks the logical value of the \meta{boolean}.
% If it is \texttt{true} the \meta{code} is placed in the input stream
% and expanded. After the completion of the \meta{code} the truth
% of the \meta{boolean} is re-evaluated. The process then loops
@@ -627,7 +627,7 @@
% \begin{syntax}
% \cs{bool_until_do:nn} \Arg{boolean expression} \Arg{code}
% \end{syntax}
-% This function firsts checks the logical value of the
+% This function first checks the logical value of the
% \meta{boolean expression} (as described for \cs{bool_if:nTF}).
% If it is \texttt{false} the \meta{code} is placed in the input stream
% and expanded. After the completion of the \meta{code} the truth
@@ -639,7 +639,7 @@
% \begin{syntax}
% \cs{bool_while_do:nn} \Arg{boolean expression} \Arg{code}
% \end{syntax}
-% This function firsts checks the logical value of the
+% This function first checks the logical value of the
% \meta{boolean expression} (as described for \cs{bool_if:nTF}).
% If it is \texttt{true} the \meta{code} is placed in the input stream
% and expanded. After the completion of the \meta{code} the truth
@@ -808,7 +808,8 @@
% \cs{prg_break:n} \Arg{code} \ldots{} \cs{prg_break_point:}
% \end{syntax}
% Breaks a recursion which has no \meta{ending code} and which is not
-% a user-breakable mapping (see for instance \cs{prop_get:Nn}), and
+% a user-breakable mapping (see for instance
+% implementation of \cs{int_step_function:nnnN}), and
% inserts the \meta{code} in the input stream.
% \end{function}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
index 69cafe1cff4..8fb7648af53 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -60,7 +60,7 @@
% Each entry in a property list must have a unique \meta{key}: if an entry is
% added to a property list which already contains the \meta{key} then the new
% entry overwrites the existing one. The \meta{keys} are compared on a
-% string basis, using the same method as \cs{str_if_eq:nn}.
+% string basis, using the same method as \cs{str_if_eq:nnTF}.
%
% Property lists are intended for storing key-based information for use within
% code. This is in contrast to key--value lists, which are a form of
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
index 1a1e1aaf1ff..d5152295827 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
index 87dfcec47b1..cd7bd9f33b0 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -921,7 +921,7 @@
% \item Optimize states with a single \cs[no-index]{__regex_action_free:n}.
% \item Optimize the use of \cs[no-index]{__regex_action_success:} by inserting it
% in state $2$ directly instead of having an extra transition.
-% \item Optimize the use of \cs{int_step_...} functions.
+% \item Optimize the use of \cs[no-index]{int_step_...} functions.
% \item Groups don't capture within regexes for csnames; optimize and
% document.
% \item Better \enquote{show} for anchors, properties, and catcode tests.
@@ -930,7 +930,7 @@
% numbers.
% \item Instead of checking whether the character is special or
% alphanumeric using its character code, check if it is special in
-% regexes with \cs{cs_if_exist} tests.
+% regexes with \cs[no-index]{cs_if_exist} tests.
% \end{itemize}
%
% The following features are likely to be implemented at some point
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
index 9572261d466..56662dc6235 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
index 0371b7ecad4..3130ef85970 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
index 6837e7fb0ea..0a987712f32 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
index f4bfaf2c2c1..c4fc416d428 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
index 300a779bd1f..99c0f980a51 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -752,7 +752,7 @@
% \item Case changing text for typesetting: see the
% \cs[index=text_lowercase:n]{text_lowercase:n(n)},
% \cs[index=text_uppercase:n]{text_uppercase:n(n)} and
-% \cs[index=text_titlecase:n]{text_titlecase:n(n)} functions which
+% \cs[index=text_titlecase_all:n]{text_titlecase_(all|once):n(n)} functions which
% correctly deal with context-dependence and other factors appropriate
% to text case changing.
% \end{itemize}
@@ -1138,7 +1138,7 @@
% \end{macro}
%
% \begin{macro}[EXP]{\@@_if_eq:nn}
-% String comparisons rely on the primitive \cs[index=pdfstrcmp]{(pdf)strcmp},
+% String comparisons rely on the primitive \tn[index=pdfstrcmp]{(pdf)strcmp},
% so we define a new name for it.
% \begin{macrocode}
\cs_new_eq:NN \@@_if_eq:nn \tex_strcmp:D
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
index 5e57590767f..577e4daa199 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -299,7 +299,7 @@
% enabled. This returns false if unrestricted shell escape is
% enabled. Unrestricted shell escape is not considered a superset
% of restricted shell escape in this case. To find whether any
-% shell escape is enabled use \cs{sys_if_shell:}.
+% shell escape is enabled use \cs{sys_if_shell:TF}.
% \end{function}
%
% \begin{function}[added = 2017-05-27]
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
index 0e20a797f09..e34e9043a54 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -77,16 +77,17 @@
% {
% \text_lowercase:n,
% \text_uppercase:n,
-% \text_titlecase:n,
+% \text_titlecase_all:n,
% \text_titlecase_first:n
% }
% \begin{macro}[EXP]
% {
% \text_lowercase:nn,
% \text_uppercase:nn,
-% \text_titlecase:nn,
+% \text_titlecase_all:nn,
% \text_titlecase_first:nn
% }
+% \begin{macro}[EXP]{\@@_change_case:nnn}
% The user level functions here are all wrappers around the internal
% functions for case changing.
% \begin{macrocode}
@@ -94,31 +95,34 @@
{ \@@_change_case:nnn { lower } { } {#1} }
\cs_new:Npn \text_uppercase:n #1
{ \@@_change_case:nnn { upper } { } {#1} }
-\cs_new:Npn \text_titlecase:n #1
+\cs_new:Npn \text_titlecase_all:n #1
{ \@@_change_case:nnn { title } { } {#1} }
\cs_new:Npn \text_titlecase_first:n #1
- { \@@_change_case:nnn { titleonly } { } {#1} }
+ { \@@_change_case:nnnn { title } { break } { } {#1} }
\cs_new:Npn \text_lowercase:nn #1#2
{ \@@_change_case:nnn { lower } {#1} {#2} }
\cs_new:Npn \text_uppercase:nn #1#2
{ \@@_change_case:nnn { upper } {#1} {#2} }
-\cs_new:Npn \text_titlecase:nn #1#2
+\cs_new:Npn \text_titlecase_all:nn #1#2
{ \@@_change_case:nnn { title } {#1} {#2} }
\cs_new:Npn \text_titlecase_first:nn #1#2
- { \@@_change_case:nnn { titleonly } {#1} {#2} }
+ { \@@_change_case:nnnn { title } { break } {#1} {#2} }
+\cs_new:Npn \@@_change_case:nnn #1#2#3
+ { \@@_change_case:nnnn {#1} {#1} {#2} {#3} }
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}[EXP]
% {
-% \@@_change_case:nnn ,
-% \@@_change_case_auxi:nnn ,
-% \@@_change_case_auxii:nnn
+% \@@_change_case:nnnn ,
+% \@@_change_case_auxi:nnnn ,
+% \@@_change_case_auxii:nnnn
% }
-% \begin{macro}[EXP]{\@@_change_case_BCP:nnn}
-% \begin{macro}[EXP]{\@@_change_case_BCP:nnw}
-% \begin{macro}[EXP]{\@@_change_case_BCP:nnnnw}
+% \begin{macro}[EXP]{\@@_change_case_BCP:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_BCP:nnnw}
+% \begin{macro}[EXP]{\@@_change_case_BCP:nnnnnw}
% \begin{macro}[EXP]
% {
% \@@_change_case_store:n, \@@_change_case_store:o,
@@ -128,74 +132,69 @@
% \begin{macro}[EXP]{\@@_change_case_store:nw}
% \begin{macro}[EXP]{\@@_change_case_result:n}
% \begin{macro}[EXP]{\@@_change_case_end:w}
-% \begin{macro}[EXP]{\@@_change_case_loop:nnw}
-% \begin{macro}[EXP]{\@@_change_case_break:w}
+% \begin{macro}[EXP]{\@@_change_case_loop:nnnw}
+% \begin{macro}[EXP]{\@@_change_case_break:w, \@@_change_case_break_aux:w}
% \begin{macro}[EXP]
% {
-% \@@_change_case_group_lower:nnn ,
-% \@@_change_case_group_upper:nnn ,
-% \@@_change_case_group_title:nnn ,
-% \@@_change_case_group_titleonly:nnn
+% \@@_change_case_group_lower:nnnn ,
+% \@@_change_case_group_upper:nnnn ,
+% \@@_change_case_group_title:nnnn
% }
-% \begin{macro}[EXP]{\@@_change_case_space:nnw}
% \begin{macro}[EXP]
-% {\@@_change_case_N_type:nnN, \@@_change_case_N_type_aux:nnN}
-% \begin{macro}[EXP]{\@@_change_case_N_type:nnnN}
-% \begin{macro}[EXP]{\@@_change_case_math_search:nnNNN}
-% \begin{macro}[EXP]{\@@_change_case_math_loop:nnNw}
-% \begin{macro}[EXP]{\@@_change_case_math_N_type:nnNN}
-% \begin{macro}[EXP]{\@@_change_case_math_group:nnNn}
-% \begin{macro}[EXP]{\@@_change_case_math_space:nnNw}
-% \begin{macro}[EXP]{\@@_change_case_cs_check:nnN}
-% \begin{macro}[EXP]{\@@_change_case_exclude:nnN}
-% \begin{macro}[EXP]{\@@_change_case_exclude:nnnN}
-% \begin{macro}[EXP]{\@@_change_case_exclude:nnNN}
-% \begin{macro}[EXP]{\@@_change_case_exclude:nnNw}
-% \begin{macro}[EXP]{\@@_change_case_exclude:nnNnn}
-% \begin{macro}[EXP]{\@@_change_case_replace:nnN}
-% \begin{macro}[EXP]{\@@_change_case_replace:nnn, \@@_change_case_replace:vnn}
-% \begin{macro}[EXP]{\@@_change_case_switch:nnN}
+% {\@@_change_case_space:nnnw, \@@_change_case_space_break:nnnw}
% \begin{macro}[EXP]
-% {
-% \@@_change_case_switch_lower:nnNnnnn ,
-% \@@_change_case_switch_upper:nnNnnnn ,
-% \@@_change_case_switch_title:nnNnnnn ,
-% \@@_change_case_switch_titleonly:nnNnnnn
-% }
+% {\@@_change_case_N_type:nnnN, \@@_change_case_N_type_aux:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_N_type:nnnnN}
+% \begin{macro}[EXP]{\@@_change_case_math_search:nnnNNN}
+% \begin{macro}[EXP]{\@@_change_case_math_loop:nnnNw}
+% \begin{macro}[EXP]{\@@_change_case_math_N_type:nnnNN}
+% \begin{macro}[EXP]{\@@_change_case_math_group:nnnNn}
+% \begin{macro}[EXP]{\@@_change_case_math_space:nnnNw}
+% \begin{macro}[EXP]{\@@_change_case_cs_check:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_exclude:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_exclude:nnnnN}
+% \begin{macro}[EXP]{\@@_change_case_exclude:nnnNN}
+% \begin{macro}[EXP]{\@@_change_case_exclude:nnnNw}
+% \begin{macro}[EXP]{\@@_change_case_exclude:nnnNnn}
+% \begin{macro}[EXP]{\@@_change_case_replace:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_replace:nnnn, \@@_change_case_replace:vnnn}
+% \begin{macro}[EXP]{\@@_change_case_switch:nnnN}
% \begin{macro}[EXP]
% {
-% \@@_change_case_letterlike_lower:nnN ,
-% \@@_change_case_letterlike_upper:nnN ,
-% \@@_change_case_letterlike_title:nnN ,
-% \@@_change_case_letterlike_titleonly:nnN
+% \@@_change_case_switch_lower:nnnNnnnn ,
+% \@@_change_case_switch_upper:nnnNnnnn ,
+% \@@_change_case_switch_title:nnnNnnnn
% }
-% \begin{macro}[EXP]{\@@_change_case_letterlike:nnnnN}
+% \begin{macro}[EXP]{\@@_change_case_skip:nnw}
+% \begin{macro}[EXP]{\@@_change_case_skip_N_type:nnN}
+% \begin{macro}[EXP]{\@@_change_case_skip_group:nnn}
+% \begin{macro}[EXP]{\@@_change_case_skip_space:nnw}
% \begin{macro}[EXP]
% {
-% \@@_change_case_custom_lower:nnn ,
-% \@@_change_case_custom_title:nnn ,
-% \@@_change_case_custom_upper:nnn ,
-% \@@_change_case_custom_titleonly:nnn
+% \@@_change_case_letterlike_lower:nnnN ,
+% \@@_change_case_letterlike_upper:nnnN ,
+% \@@_change_case_letterlike_title:nnnN
% }
-% \begin{macro}[EXP]{\@@_change_case_custom:nnn}
+% \begin{macro}[EXP]{\@@_change_case_letterlike:nnnnnN}
% \begin{macro}[EXP]
% {
-% \@@_change_case_codepoint_lower:nnn ,
-% \@@_change_case_codepoint_upper:nnn ,
-% \@@_change_case_codepoint_title:nnn ,
-% \@@_change_case_codepoint_titleonly:nnn
+% \@@_change_case_custom_lower:nnnn ,
+% \@@_change_case_custom_title:nnnn ,
+% \@@_change_case_custom_upper:nnnn
% }
-% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnn}
-% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnw}
-% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_custom:nnnnn}
% \begin{macro}[EXP]
% {
-% \@@_change_case_codepoint_title:nn ,
-% \@@_change_case_codepoint_titleonly:nn
+% \@@_change_case_codepoint_lower:nnnn ,
+% \@@_change_case_codepoint_upper:nnnn ,
+% \@@_change_case_codepoint_title:nnnn
% }
-% \begin{macro}[EXP]{\@@_change_case_codepoint_title:nnnn}
-% \begin{macro}[EXP]
-% {\@@_change_case_codepoint:nnnn, \@@_change_case_codepoint_aux:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnnn}
+% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnnw}
+% \begin{macro}[EXP]{\@@_change_case_lower_sigma:nnnnN}
+% \begin{macro}[EXP]{\@@_change_case_codepoint_title:nnn}
+% \begin{macro}[EXP]{\@@_change_case_codepoint_title:nnnnn}
+% \begin{macro}[EXP]{\@@_change_case_codepoint:nnnnn}
% \begin{macro}[EXP]{\@@_change_case_codepoint:nn}
% \begin{macro}[EXP]
% {
@@ -203,13 +202,15 @@
% \@@_change_case_codepoint:fnn ,
% \@@_change_case_codepoint_aux:nnn
% }
+% \begin{macro}[EXP]{\@@_change_case_codepoint_aux:nnn}
+% \begin{macro}[EXP]{\@@_change_case_codepoint_aux:nn}
+% \begin{macro}[EXP]{\@@_change_case_catcode:nn}
% \begin{macro}[EXP]
% {
-% \@@_change_case_next_lower:nn ,
-% \@@_change_case_next_upper:nn ,
-% \@@_change_case_next_title:nn ,
-% \@@_change_case_next_titleonly:nn ,
-% \@@_change_case_next_end:nn
+% \@@_change_case_next_lower:nnn ,
+% \@@_change_case_next_upper:nnn ,
+% \@@_change_case_next_title:nnn ,
+% \@@_change_case_next_end:nnn
% }
% As for the expansion code, the business end of case changing is the
% handling of \texttt{N}-type tokens. First, we expand the input fully
@@ -231,45 +232,50 @@
% wrap the entire result in exactly one \cs{exp_not:n}, or rather in the
% kernel version.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case:nnn #1#2#3
+\cs_new:Npn \@@_change_case:nnnn #1#2#3#4
{
\__kernel_exp_not:w \exp_after:wN
{
\exp:w
- \exp_args:Ne \@@_change_case_auxi:nnn
- { \text_expand:n {#3} }
- {#1} {#2}
+ \exp_args:Ne \@@_change_case_auxi:nnnn
+ { \text_expand:n {#4} }
+ {#1} {#2} {#3}
}
}
-\cs_new:Npn \@@_change_case_auxi:nnn #1#2#3
- { \exp_args:No \@@_change_case_BCP:nnn { \tl_to_str:n {#3} } {#1} {#2} }
-\cs_new:Npe \@@_change_case_BCP:nnn #1#2#3
+\cs_new:Npn \@@_change_case_auxi:nnnn #1#2#3#4
{
- \exp_not:N \@@_change_case_BCP:nnw
- {#2} {#3} #1 \tl_to_str:n { -x- -x- } \exp_not:N \q_@@_stop
+ \exp_args:No \@@_change_case_BCP:nnnn
+ { \tl_to_str:n {#4} } {#1} {#2} {#3}
+ }
+\cs_new:Npe \@@_change_case_BCP:nnnn #1#2#3#4
+ {
+ \exp_not:N \@@_change_case_BCP:nnnw
+ {#2} {#3} {#4} #1 \tl_to_str:n { -x- -x- } \exp_not:N \q_@@_stop
}
\use:e
{
- \cs_new:Npn \exp_not:N \@@_change_case_BCP:nnw
- #1#2#3 \tl_to_str:n { -x- } #4 \tl_to_str:n { -x- } #5
+ \cs_new:Npn \exp_not:N \@@_change_case_BCP:nnnw
+ #1#2#3#4 \tl_to_str:n { -x- } #5 \tl_to_str:n { -x- } #6
\exp_not:N \q_@@_stop
}
- { \@@_change_case_BCP:nnnnw {#1} {#2} {#4} {#3} #3 - - \q_@@_stop }
-\cs_new:Npn \@@_change_case_BCP:nnnnw #1#2#3#4#5 - #6 - #7 \q_@@_stop
+ { \@@_change_case_BCP:nnnnnw {#1} {#2} {#3} {#5} {#4} #4 - \q_@@_stop }
+\cs_new:Npn \@@_change_case_BCP:nnnnnw #1#2#3#4#5#6 - #7 \q_@@_stop
{
- \cs_if_exist:cTF { @@_change_case_ #2 _ #5 -x- #3 :nnnn }
- { \@@_change_case_auxii:nnn {#1} {#2} { #5 -x- #3 } }
+ \bool_lazy_or:nnTF
+ { \cs_if_exist_p:c { @@_change_case_ #2 _ #6 -x- #4 :nnnnn } }
+ { \tl_if_exist_p:c { l_@@_ #2 case_special_ #6 -x- #4 _tl } }
+ { \@@_change_case_auxii:nnnn {#1} {#2} {#3} { #6 -x- #4 } }
{
- \cs_if_exist:cTF { @@_change_case_ #2 _ #5 :nnnn }
- { \@@_change_case_auxii:nnn {#1} {#2} {#5} }
- { \@@_change_case_auxii:nnn {#1} {#2} {#4} }
+ \cs_if_exist:cTF { @@_change_case_ #2 _ #6 :nnnnn }
+ { \@@_change_case_auxii:nnnn {#1} {#2} {#3} {#6} }
+ { \@@_change_case_auxii:nnnn {#1} {#2} {#3} {#5} }
}
}
-\cs_new:Npn \@@_change_case_auxii:nnn #1#2#3
+\cs_new:Npn \@@_change_case_auxii:nnnn #1#2#3#4
{
\group_align_safe_begin:
- \cs_if_exist_use:c { @@_change_case_boundary_ #2 _ #3 :Nnnw }
- \@@_change_case_loop:nnw {#2} {#3} #1
+ \cs_if_exist_use:c { @@_change_case_boundary_ #2 _ #4 :Nnnnw }
+ \@@_change_case_loop:nnnw {#2} {#3} {#4} #1
\q_@@_recursion_tail \q_@@_recursion_stop
\@@_change_case_result:n { }
}
@@ -290,20 +296,23 @@
% \end{macrocode}
% The main loop is the standard \texttt{tl action} type.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_loop:nnw #1#2#3 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_loop:nnnw #1#2#3#4 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_change_case_N_type:nnN }
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_change_case_N_type:nnnN }
{
- \tl_if_head_is_group:nTF {#3}
- { \use:c { @@_change_case_group_ #1 :nnn } }
- { \@@_change_case_space:nnw }
+ \tl_if_head_is_group:nTF {#4}
+ { \use:c { @@_change_case_group_ #1 :nnnn } }
+ { \@@_change_case_space:nnnw }
}
- {#1} {#2} #3 \q_@@_recursion_stop
+ {#1} {#2} {#3} #4 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_break:w #1 \q_@@_recursion_tail \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_break:w
+ { \@@_change_case_break_aux:w \prg_do_nothing: }
+\cs_new:Npn \@@_change_case_break_aux:w
+ #1 \q_@@_recursion_tail \q_@@_recursion_stop
{
- \@@_change_case_store:n {#1}
+ \@@_change_case_store:o {#1}
\@@_change_case_end:w
}
% \end{macrocode}
@@ -315,53 +324,47 @@
% having too much testing, we use a two-step process here to allow the
% titlecase functions to be separate.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_group_lower:nnn #1#2#3
+\cs_new:Npn \@@_change_case_group_lower:nnnn #1#2#3#4
{
\@@_change_case_store:o
{
\exp_after:wN
{
\exp:w
- \@@_change_case_auxii:nnn {#3} {#1} {#2}
+ \@@_change_case_auxii:nnnn {#4} {#1} {#2} {#3}
}
}
- \@@_change_case_loop:nnw {#1} {#2}
+ \@@_change_case_loop:nnnw {#1} {#2} {#3}
}
-\cs_new_eq:NN \@@_change_case_group_upper:nnn
- \@@_change_case_group_lower:nnn
-\cs_new:Npn \@@_change_case_group_title:nnn #1#2#3
+\cs_new_eq:NN \@@_change_case_group_upper:nnnn
+ \@@_change_case_group_lower:nnnn
+\cs_new:Npn \@@_change_case_group_title:nnnn #1#2#3#4
{
\@@_change_case_store:o
{
\exp_after:wN
{
\exp:w
- \@@_change_case_auxii:nnn {#3} {#1} {#2}
+ \@@_change_case_auxii:nnnn {#4} {#1} {#2} {#3}
}
}
- \@@_change_case_loop:nnw { lower } {#2}
- }
-\cs_new:Npn \@@_change_case_group_titleonly:nnn #1#2#3
- {
- \@@_change_case_store:o
- {
- \exp_after:wN
- {
- \exp:w
- \@@_change_case_auxii:nnn {#3} {#1} {#2}
- }
- }
- \@@_change_case_break:w
+ \@@_change_case_skip:nnw {#2} {#3}
}
\use:e
{
- \cs_new:Npn \exp_not:N \@@_change_case_space:nnw #1#2 \c_space_tl
+ \cs_new:Npn \exp_not:N \@@_change_case_space:nnnw #1#2#3 \c_space_tl
}
{
\@@_change_case_store:n { ~ }
- \cs_if_exist_use:c { @@_change_case_boundary_ #1 _ #2 :Nnnw }
- \@@_change_case_loop:nnw {#1} {#2}
+ \cs_if_exist_use:cF { @@_change_case_space_ #2 :nnn }
+ {
+ \cs_if_exist_use:c { @@_change_case_boundary_ #1 _ #3 :Nnnnw }
+ \@@_change_case_loop:nnnw
+ }
+ {#2} {#2} {#3}
}
+\cs_new:Npn \@@_change_case_space_break:nnn #1#2#3
+ { \@@_change_case_break:w }
% \end{macrocode}
% The first step of handling \texttt{N}-type tokens is to filter out the
% end-of-loop. That has to be done separately from the first real step
@@ -371,85 +374,85 @@
% (i.e.~there is no assumption of \enquote{well-behaved} input in terms of
% math mode).
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_N_type:nnN #1#2#3
+\cs_new:Npn \@@_change_case_N_type:nnnN #1#2#3#4
{
- \@@_if_q_recursion_tail_stop_do:Nn #3
+ \@@_if_q_recursion_tail_stop_do:Nn #4
{ \@@_change_case_end:w }
- \@@_change_case_N_type_aux:nnN {#1} {#2} #3
+ \@@_change_case_N_type_aux:nnnN {#1} {#2} {#3} #4
}
-\cs_new:Npn \@@_change_case_N_type_aux:nnN #1#2#3
+\cs_new:Npn \@@_change_case_N_type_aux:nnnN #1#2#3#4
{
- \exp_args:NV \@@_change_case_N_type:nnnN
- \l_text_math_delims_tl {#1} {#2} #3
+ \exp_args:NV \@@_change_case_N_type:nnnnN
+ \l_text_math_delims_tl {#1} {#2} {#3} #4
}
-\cs_new:Npn \@@_change_case_N_type:nnnN #1#2#3#4
+\cs_new:Npn \@@_change_case_N_type:nnnnN #1#2#3#4#5
{
- \@@_change_case_math_search:nnNNN {#2} {#3} #4 #1
+ \@@_change_case_math_search:nnnNNN {#2} {#3} {#4} #5 #1
\q_@@_recursion_tail \q_@@_recursion_tail
\q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_math_search:nnNNN #1#2#3#4#5
+\cs_new:Npn \@@_change_case_math_search:nnnNNN #1#2#3#4#5#6
{
- \@@_if_q_recursion_tail_stop_do:Nn #4
- { \@@_change_case_cs_check:nnN {#1} {#2} #3 }
- \token_if_eq_meaning:NNTF #3 #4
+ \@@_if_q_recursion_tail_stop_do:Nn #5
+ { \@@_change_case_cs_check:nnnN {#1} {#2} {#3} #4 }
+ \token_if_eq_meaning:NNTF #4 #5
{
\@@_use_i_delimit_by_q_recursion_stop:nw
{
- \@@_change_case_store:n {#3}
- \@@_change_case_math_loop:nnNw {#1} {#2} #5
+ \@@_change_case_store:n {#4}
+ \@@_change_case_math_loop:nnnNw {#1} {#2} {#3} #6
}
}
- { \@@_change_case_math_search:nnNNN {#1} {#2} #3 }
+ { \@@_change_case_math_search:nnnNNN {#1} {#2} {#3} #4 }
}
-\cs_new:Npn \@@_change_case_math_loop:nnNw #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_math_loop:nnnNw #1#2#3#4#5 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_math_N_type:nnNN }
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_math_N_type:nnnNN }
{
- \tl_if_head_is_group:nTF {#4}
- { \@@_change_case_math_group:nnNn }
- { \@@_change_case_math_space:nnNw }
+ \tl_if_head_is_group:nTF {#5}
+ { \@@_change_case_math_group:nnnNn }
+ { \@@_change_case_math_space:nnnNw }
}
- {#1} {#2} #3 #4 \q_@@_recursion_stop
+ {#1} {#2} {#3} #4 #5 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_math_N_type:nnNN #1#2#3#4
+\cs_new:Npn \@@_change_case_math_N_type:nnnNN #1#2#3#4#5
{
- \@@_if_q_recursion_tail_stop_do:Nn #4
+ \@@_if_q_recursion_tail_stop_do:Nn #5
{ \@@_change_case_end:w }
- \@@_change_case_store:n {#4}
- \token_if_eq_meaning:NNTF #4 #3
- { \@@_change_case_loop:nnw {#1} {#2} }
- { \@@_change_case_math_loop:nnNw {#1} {#2} #3 }
+ \@@_change_case_store:n {#5}
+ \token_if_eq_meaning:NNTF #5 #4
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} }
+ { \@@_change_case_math_loop:nnnNw {#1} {#2} {#3} #4 }
}
-\cs_new:Npn \@@_change_case_math_group:nnNn #1#2#3#4
+\cs_new:Npn \@@_change_case_math_group:nnnNn #1#2#3#4#5
{
- \@@_change_case_store:n { {#4} }
- \@@_change_case_math_loop:nnNw {#1} {#2} #3
+ \@@_change_case_store:n { {#5} }
+ \@@_change_case_math_loop:nnnNw {#1} {#2} {#3} #4
}
\use:e
{
- \cs_new:Npn \exp_not:N \@@_change_case_math_space:nnNw #1#2#3
+ \cs_new:Npn \exp_not:N \@@_change_case_math_space:nnnNw #1#2#3#4
\c_space_tl
}
{
\@@_change_case_store:n { ~ }
- \@@_change_case_math_loop:nnNw {#1} {#2} #3
+ \@@_change_case_math_loop:nnnNw {#1} {#2} {#3} #4
}
% \end{macrocode}
% Once potential math-mode cases are filtered out the next stage is to
% test if the token grabbed is a control sequence: the two routes the code
% may take are then very different.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_cs_check:nnN #1#2#3
+\cs_new:Npn \@@_change_case_cs_check:nnnN #1#2#3#4
{
- \token_if_cs:NTF #3
- { \@@_change_case_exclude:nnN {#1} {#2} }
+ \token_if_cs:NTF #4
+ { \@@_change_case_exclude:nnnN {#1} {#2} {#3} }
{
\@@_codepoint_process:nN
- { \use:c { @@_change_case_custom_ #1 :nnn } {#1} {#2} }
+ { \use:c { @@_change_case_custom_ #1 :nnnn } {#1} {#2} {#3} }
}
- #3
+ #4
}
% \end{macrocode}
% To deal with a control sequence there is first a need to test if it is
@@ -457,92 +460,115 @@
% done using a loop as for the other special cases. If a hit is found then
% the argument is grabbed and passed through as-is.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_exclude:nnN #1#2#3
+\cs_new:Npn \@@_change_case_exclude:nnnN #1#2#3#4
{
- \exp_args:Ne \@@_change_case_exclude:nnnN
+ \exp_args:Ne \@@_change_case_exclude:nnnnN
{
\exp_not:V \l_text_math_arg_tl
\exp_not:V \l_text_case_exclude_arg_tl
}
- {#1} {#2} #3
+ {#1} {#2} {#3} #4
}
-\cs_new:Npn \@@_change_case_exclude:nnnN #1#2#3#4
+\cs_new:Npn \@@_change_case_exclude:nnnnN #1#2#3#4#5
{
- \@@_change_case_exclude:nnNN {#2} {#3} #4 #1
+ \@@_change_case_exclude:nnnNN {#2} {#3} {#4} #5 #1
\q_@@_recursion_tail \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_exclude:nnNN #1#2#3#4
+\cs_new:Npn \@@_change_case_exclude:nnnNN #1#2#3#4#5
{
- \@@_if_q_recursion_tail_stop_do:Nn #4
- { \@@_change_case_replace:nnN {#1} {#2} #3 }
- \str_if_eq:nnTF {#3} {#4}
+ \@@_if_q_recursion_tail_stop_do:Nn #5
+ { \@@_change_case_replace:nnnN {#1} {#2} {#3} #4 }
+ \str_if_eq:nnTF {#4} {#5}
{
\@@_use_i_delimit_by_q_recursion_stop:nw
- { \@@_change_case_exclude:nnNw {#1} {#2} #3 }
+ { \@@_change_case_exclude:nnnNw {#1} {#2} {#3} #4 }
}
- { \@@_change_case_exclude:nnNN {#1} {#2} #3 }
+ { \@@_change_case_exclude:nnnNN {#1} {#2} {#3} #4 }
}
-\cs_new:Npn \@@_change_case_exclude:nnNw #1#2#3#4#
- { \@@_change_case_exclude:nnNnn {#1} {#2} {#3} {#4} }
-\cs_new:Npn \@@_change_case_exclude:nnNnn #1#2#3#4#5
+\cs_new:Npn \@@_change_case_exclude:nnnNw #1#2#3#4#5#
+ { \@@_change_case_exclude:nnnNnn {#1} {#2} {#3} {#4} {#5} }
+\cs_new:Npn \@@_change_case_exclude:nnnNnn #1#2#3#4#5#6
{
- \tl_if_blank:nTF {#4}
- { \@@_change_case_store:n { #3 {#5} } }
+ \tl_if_blank:nTF {#5}
+ { \@@_change_case_store:n { #4 {#6} } }
{
\@@_change_case_store:o
{
- \exp_after:wN #3
- \exp:w \@@_change_case_auxii:nnn {#4} {#1} {#2}
- {#5}
+ \exp_after:wN #4
+ \exp:w \@@_change_case_auxii:nnnn {#5} {#1} {#2} {#3}
+ {#6}
}
}
- \@@_change_case_loop:nnw {#1} {#2}
+ \@@_change_case_loop:nnnw {#1} {#2} {#3}
}
% \end{macrocode}
% Deal with any specialist replacement for case changing.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_replace:nnN #1#2#3
+\cs_new:Npn \@@_change_case_replace:nnnN #1#2#3#4
{
- \cs_if_exist:cTF { l_@@_case_ \token_to_str:N #3 _tl }
+ \cs_if_exist:cTF { l_@@_case_ \token_to_str:N #4 _tl }
{
- \@@_change_case_replace:vnn
- { l_@@_case_ \token_to_str:N #3 _tl } {#1} {#2}
+ \@@_change_case_replace:vnnn
+ { l_@@_case_ \token_to_str:N #4 _tl } {#1} {#2} {#3}
}
- { \@@_change_case_switch:nnN {#1} {#2} #3 }
+ { \@@_change_case_switch:nnnN {#1} {#2} {#3} #4 }
}
-\cs_new:Npn \@@_change_case_replace:nnn #1#2#3
- { \@@_change_case_loop:nnw {#2} {#3} #1 }
-\cs_generate_variant:Nn \@@_change_case_replace:nnn { v }
+\cs_new:Npn \@@_change_case_replace:nnnn #1#2#3#4
+ { \@@_change_case_loop:nnnw {#2} {#3} {#4} #1 }
+\cs_generate_variant:Nn \@@_change_case_replace:nnnn { v }
% \end{macrocode}
% Allow for manually-controlled case switching.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_switch:nnN #1#2#3
+\cs_new:Npn \@@_change_case_switch:nnnN #1#2#3#4
+ {
+ \cs_if_eq:NNTF #4 \text_case_switch:nnnn
+ { \use:c { @@_change_case_switch_ #1 :nnnNnnnn } }
+ { \use:c { @@_change_case_letterlike_ #1 :nnnN } }
+ {#1} {#2} {#3} #4
+ }
+\cs_new:Npn \@@_change_case_switch_lower:nnnNnnnn #1#2#3#4#5#6#7#8
{
- \cs_if_eq:NNTF #3 \text_case_switch:nnnn
- { \use:c { @@_change_case_switch_ #1 :nnNnnnn } }
- { \use:c { @@_change_case_letterlike_ #1 :nnN } }
- {#1} {#2} #3
+ \@@_change_case_store:n {#7}
+ \@@_change_case_loop:nnnw {#1} {#2} {#3}
}
-\cs_new:Npn \@@_change_case_switch_lower:nnNnnnn #1#2#3#4#5#6#7
+\cs_new:Npn \@@_change_case_switch_upper:nnnNnnnn #1#2#3#4#5#6#7#8
{
\@@_change_case_store:n {#6}
- \@@_change_case_loop:nnw {#1} {#2}
+ \@@_change_case_loop:nnnw {#1} {#2} {#3}
}
-\cs_new:Npn \@@_change_case_switch_upper:nnNnnnn #1#2#3#4#5#6#7
+\cs_new:Npn \@@_change_case_switch_title:nnnNnnnn #1#2#3#4#5#6#7#8
{
- \@@_change_case_store:n {#5}
- \@@_change_case_loop:nnw {#1} {#2}
+ \@@_change_case_store:n {#8}
+ \@@_change_case_skip:nnw {#2} {#3}
}
-\cs_new:Npn \@@_change_case_switch_title:nnNnnnn #1#2#3#4#5#6#7
+% \end{macrocode}
+% Skip over material quickly after titlecase-first-only initials
+% \begin{macrocode}
+\cs_new:Npn \@@_change_case_skip:nnw #1#2#3 \q_@@_recursion_stop
{
- \@@_change_case_store:n {#7}
- \@@_change_case_loop:nnw {#1} {#2}
+ \tl_if_head_is_N_type:nTF {#3}
+ { \@@_change_case_skip_N_type:nnN }
+ {
+ \tl_if_head_is_group:nTF {#3}
+ { \@@_change_case_skip_group:nnn }
+ { \@@_change_case_skip_space:nnw }
+ }
+ {#1} {#2} #3 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_switch_titleonly:nnNnnnn #1#2#3#4#5#6#7
+\cs_new:Npn \@@_change_case_skip_N_type:nnN #1#2#3
{
- \@@_change_case_store:n {#7}
- \@@_change_case_break:w
+ \@@_if_q_recursion_tail_stop_do:Nn #3
+ { \@@_change_case_end:w }
+ \@@_change_case_store:n {#3}
+ \@@_change_case_skip:nnw {#1} {#2}
+ }
+\cs_new:Npn \@@_change_case_skip_group:nnn #1#2#3
+ {
+ \@@_change_case_store:n { {#3} }
+ \@@_change_case_skip:nnw {#1} {#2}
}
+\cs_new:Npn \@@_change_case_skip_space:nnw #1#2
+ { \@@_change_case_space:nnnw {#1} {#1} {#2} }
% \end{macrocode}
% Letter-like commands may still be present: they are set up using a simple
% lookup approach, so can easily be handled with no loop. If there is no
@@ -550,68 +576,64 @@
% are all available only in upper- and lowercase, so titlecasing maps to the
% uppercase version.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_letterlike_lower:nnN #1#2#3
- { \@@_change_case_letterlike:nnnnN {#1} {#1} {#1} {#2} #3 }
-\cs_new_eq:NN \@@_change_case_letterlike_upper:nnN
- \@@_change_case_letterlike_lower:nnN
-\cs_new:Npn \@@_change_case_letterlike_title:nnN #1#2#3
- { \@@_change_case_letterlike:nnnnN { upper } { lower } {#1} {#2} #3 }
-\cs_new:Npn \@@_change_case_letterlike_titleonly:nnN #1#2#3
- { \@@_change_case_letterlike:nnnnN { upper } { end } {#1} {#2} #3 }
-\cs_new:Npn \@@_change_case_letterlike:nnnnN #1#2#3#4#5
- {
- \cs_if_exist:cTF { c_@@_ #1 case_ \token_to_str:N #5 _tl }
+\cs_new:Npn \@@_change_case_letterlike_lower:nnnN #1#2#3#4
+ { \@@_change_case_letterlike:nnnnnN {#1} {#1} {#1} {#2} {#3} #4 }
+\cs_new_eq:NN \@@_change_case_letterlike_upper:nnnN
+ \@@_change_case_letterlike_lower:nnnN
+\cs_new:Npn \@@_change_case_letterlike_title:nnnN #1#2#3#4
+ { \@@_change_case_letterlike:nnnnnN { upper } { end } {#1} {#2} {#3} #4 }
+\cs_new:Npn \@@_change_case_letterlike:nnnnnN #1#2#3#4#5#6
+ {
+ \cs_if_exist:cTF { c_@@_ #1 case_ \token_to_str:N #6 _tl }
{
\@@_change_case_store:v
- { c_@@_ #1 case_ \token_to_str:N #5 _tl }
- \use:c { @@_change_case_next_ #2 :nn } {#2} {#4}
+ { c_@@_ #1 case_ \token_to_str:N #6 _tl }
+ \use:c { @@_change_case_next_ #2 :nnn } {#2} {#4} {#5}
}
{
- \@@_change_case_store:n {#5}
+ \@@_change_case_store:n {#6}
\cs_if_exist:cTF
{
c_@@_
\str_if_eq:nnTF {#1} { lower } { upper } { lower }
- case_ \token_to_str:N #5 _tl
+ case_ \token_to_str:N #6 _tl
}
- { \use:c { @@_change_case_next_ #2 :nn } {#2} {#4} }
- { \@@_change_case_loop:nnw {#3} {#4} }
+ { \use:c { @@_change_case_next_ #2 :nnn } {#2} {#4} {#5} }
+ { \@@_change_case_loop:nnnw {#3} {#4} {#5} }
}
}
% \end{macrocode}
% Check for a customised codepoint result.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_custom_lower:nnn #1#2#3
+\cs_new:Npn \@@_change_case_custom_lower:nnnn #1#2#3#4
{
- \@@_change_case_custom:nnnnn {#1} {#2} {#3} {#1}
- { \use:c { @@_change_case_codepoint_ #1 :nnn } {#1} {#2} {#3} }
+ \@@_change_case_custom:nnnnnn {#1} {#1} {#2} {#3} {#4}
+ { \use:c { @@_change_case_codepoint_ #1 :nnnn } {#1} {#2} {#3} {#4} }
}
-\cs_new_eq:NN \@@_change_case_custom_upper:nnn
- \@@_change_case_custom_lower:nnn
-\cs_new:Npn \@@_change_case_custom_title:nnn #1#2#3
+\cs_new_eq:NN \@@_change_case_custom_upper:nnnn
+ \@@_change_case_custom_lower:nnnn
+\cs_new:Npn \@@_change_case_custom_title:nnnn #1#2#3#4
{
- \@@_change_case_custom:nnnnn { title } {#2} {#3} {#1}
+ \@@_change_case_custom:nnnnnn { title } {#1} {#2} {#3} {#4}
{
- \@@_change_case_custom:nnnnn { upper } {#2} {#3} {#1}
- { \use:c { @@_change_case_codepoint_ #1 :nnn } {#1} {#2} {#3} }
+ \@@_change_case_custom:nnnnnn { upper } {#1} {#2} {#3} {#4}
+ { \use:c { @@_change_case_codepoint_ #1 :nnnn } {#1} {#2} {#3} {#4} }
}
}
-\cs_new_eq:NN \@@_change_case_custom_titleonly:nnn
- \@@_change_case_custom_title:nnn
-\cs_new:Npn \@@_change_case_custom:nnnnn #1#2#3#4#5
+\cs_new:Npn \@@_change_case_custom:nnnnnn #1#2#3#4#5#6
{
- \tl_if_exist:cTF { l_@@_ #1 case _ \tl_to_str:n {#3} _ #2 _tl }
+ \tl_if_exist:cTF { l_@@_ #1 case _ \tl_to_str:n {#5} _ #4 _tl }
{
- \@@_change_case_replace:vnn
- { l_@@_ #1 case _ \tl_to_str:n {#3} _ #2 _tl } {#4} {#2}
+ \@@_change_case_replace:vnnn
+ { l_@@_ #1 case _ \tl_to_str:n {#5} _ #4 _tl } {#2} {#3} {#4}
}
{
- \tl_if_exist:cTF { l_@@_ #1 case _ \tl_to_str:n {#3} _tl }
+ \tl_if_exist:cTF { l_@@_ #1 case _ \tl_to_str:n {#5} _tl }
{
- \@@_change_case_replace:vnn
- { l_@@_ #1 case _ \tl_to_str:n {#3} _tl } {#4} {#2}
+ \@@_change_case_replace:vnnn
+ { l_@@_ #1 case _ \tl_to_str:n {#5} _tl } {#2} {#3} {#4}
}
- {#5}
+ {#6}
}
}
% \end{macrocode}
@@ -620,17 +642,17 @@
% is there the special case of a terminal sigma. If not, then we pass to
% a simple codepoint mapping.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_codepoint_lower:nnn #1#2#3
+\cs_new:Npn \@@_change_case_codepoint_lower:nnnn #1#2#3#4
{
- \cs_if_exist_use:cF { @@_change_case_lower_ #2 :nnnn }
- { \@@_change_case_lower_sigma:nnnn }
- {#1} {#1} {#2} {#3}
+ \cs_if_exist_use:cF { @@_change_case_lower_ #3 :nnnnn }
+ { \@@_change_case_lower_sigma:nnnnn }
+ {#1} {#1} {#2} {#3} {#4}
}
-\cs_new:Npn \@@_change_case_codepoint_upper:nnn #1#2#3
+\cs_new:Npn \@@_change_case_codepoint_upper:nnnn #1#2#3#4
{
- \cs_if_exist_use:cF { @@_change_case_upper_ #2 :nnnn }
- { \@@_change_case_codepoint:nnnn }
- {#1} {#1} {#2} {#3}
+ \cs_if_exist_use:cF { @@_change_case_upper_ #3 :nnnnn }
+ { \@@_change_case_codepoint:nnnnn }
+ {#1} {#1} {#2} {#3} {#4}
}
% \end{macrocode}
% If the current character is an uppercase sigma, the a check is made on the
@@ -638,91 +660,87 @@
% then there is a look-ahead phase: the logic here is simply based on letters
% or actives (to cover $8$-bit engines).
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_lower_sigma:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_sigma:nnnnn #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "03A3 }
- { \@@_change_case_lower_sigma:nnnw {#2} }
- { \@@_change_case_codepoint:nnnn {#1} {#2} }
- {#3} {#4}
+ \@@_codepoint_compare:nNnTF {#5} = { "03A3 }
+ { \@@_change_case_lower_sigma:nnnnw {#2} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} }
+ {#3} {#4} {#5}
}
-\cs_new:Npn \@@_change_case_lower_sigma:nnnw #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_lower_sigma:nnnnw #1#2#3#4#5 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_lower_sigma:nnnN {#3} }
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_lower_sigma:nnnnN {#4} }
{
\@@_change_case_store:e
- { \codepoint_generate:nn { "03C2 } { \@@_char_catcode:N #3 } }
- \@@_change_case_loop:nnw
+ { \codepoint_generate:nn { "03C2 } { \@@_char_catcode:N #4 } }
+ \@@_change_case_loop:nnnw
}
- {#1} {#2} #4 \q_@@_recursion_stop
+ {#1} {#2} {#3} #5 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_lower_sigma:nnnN #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_sigma:nnnnN #1#2#3#4#5
{
\@@_change_case_store:e
{
\bool_lazy_or:nnTF
- { \token_if_letter_p:N #4 }
+ { \token_if_letter_p:N #5 }
{
\bool_lazy_and_p:nn
- { \token_if_active_p:N #4 }
- { \int_compare_p:nNn {`#4} > { "80 } }
+ { \token_if_active_p:N #5 }
+ { \int_compare_p:nNn {`#5} > { "80 } }
}
{ \codepoint_generate:nn { "03C3 } { \@@_char_catcode:N #1 } }
{ \codepoint_generate:nn { "03C2 } { \@@_char_catcode:N #1 } }
}
- \@@_change_case_loop:nnw {#2} {#3} #4
+ \@@_change_case_loop:nnnw {#2} {#3} {#4} #5
}
% \end{macrocode}
% For titlecasing, we need to fully expand the new character to see if it
% is a letter (or active).
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_codepoint_title:nnn #1#2#3
+\cs_new:Npn \@@_change_case_codepoint_title:nnnn #1#2#3#4
{
\bool_if:NTF \l_text_titlecase_check_letter_bool
{
- \tl_if_single:nTF {#3}
+ \tl_if_single:nTF {#4}
{
\bool_lazy_or:nnTF
- { \token_if_letter_p:N #3 }
+ { \token_if_letter_p:N #4 }
{
\bool_lazy_and_p:nn
- { \token_if_active_p:N #3 }
- { ! \int_compare_p:nNn {`#3} < { "80 } }
+ { \token_if_active_p:N #4 }
+ { ! \int_compare_p:nNn {`#4} < { "80 } }
}
- { \use:c { @@_change_case_codepoint_ #1 :nn } }
- { \@@_change_case_codepoint_title:nnnn { title } {#1} }
+ { \@@_change_case_codepoint_title:nnn }
+ { \@@_change_case_codepoint_title:nnnnn { title } {#1} }
}
- { \use:c { @@_change_case_codepoint_ #1 :nn } }
+ { \@@_change_case_codepoint_title:nnn }
}
- { \use:c { @@_change_case_codepoint_ #1 :nn } }
- {#2} {#3}
+ { \@@_change_case_codepoint_title:nnn }
+ {#2} {#3} {#4}
}
-\cs_new_eq:NN \@@_change_case_codepoint_titleonly:nnn
- \@@_change_case_codepoint_title:nnn
-\cs_new:Npn \@@_change_case_codepoint_title:nn #1#2
- { \@@_change_case_codepoint_title:nnnn { title } { lower } {#1} {#2} }
-\cs_new:Npn \@@_change_case_codepoint_titleonly:nn #1#2
- { \@@_change_case_codepoint_title:nnnn { title } { end } {#1} {#2} }
-\cs_new:Npn \@@_change_case_codepoint_title:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_codepoint_title:nnn #1#2#3
+ { \@@_change_case_codepoint_title:nnnnn { title } { end } {#1} {#2} {#3} }
+\cs_new:Npn \@@_change_case_codepoint_title:nnnnn #1#2#3#4#5
{
- \cs_if_exist_use:cF { @@_change_case_title_ #3 :nnnn }
+ \cs_if_exist_use:cF { @@_change_case_title_ #4 :nnnnn }
{
- \cs_if_exist_use:cF { @@_change_case_upper_ #3 :nnnn }
- { \@@_change_case_codepoint:nnnn }
+ \cs_if_exist_use:cF { @@_change_case_upper_ #4 :nnnnn }
+ { \@@_change_case_codepoint:nnnnn }
}
- {#1} {#2} {#3} {#4}
+ {#1} {#2} {#3} {#4} {#5}
}
-\cs_new:Npn \@@_change_case_codepoint:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_codepoint:nnnnn #1#2#3#4#5
{
\bool_lazy_and:nnTF
- { \tl_if_single_p:n {#4} }
- { \token_if_active_p:N #4 }
- { \@@_change_case_store:n {#4} }
+ { \tl_if_single_p:n {#5} }
+ { \token_if_active_p:N #5 }
+ { \@@_change_case_store:n {#5} }
{
\@@_change_case_store:e
- { \@@_change_case_codepoint:nn {#1} {#4} }
+ { \@@_change_case_codepoint:nn {#1} {#5} }
}
- \use:c { @@_change_case_next_ #2 :nn } {#2} {#3}
+ \use:c { @@_change_case_next_ #2 :nnn } {#2} {#3} {#4}
}
\cs_new:Npn \@@_change_case_codepoint:nn #1#2
{
@@ -799,16 +817,14 @@
}
}
}
-\cs_new:Npn \@@_change_case_next_lower:nn #1#2
- { \@@_change_case_loop:nnw {#1} {#2} }
-\cs_new_eq:NN \@@_change_case_next_upper:nn
- \@@_change_case_next_lower:nn
-\cs_new_eq:NN \@@_change_case_next_title:nn
- \@@_change_case_next_lower:nn
-\cs_new_eq:NN \@@_change_case_next_titleonly:nn
- \@@_change_case_next_lower:nn
-\cs_new:Npn \@@_change_case_next_end:nn #1#2
- { \@@_change_case_break:w }
+\cs_new:Npn \@@_change_case_next_lower:nnn #1#2#3
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} }
+\cs_new_eq:NN \@@_change_case_next_upper:nnn
+ \@@_change_case_next_lower:nnn
+\cs_new_eq:NN \@@_change_case_next_title:nnn
+ \@@_change_case_next_lower:nnn
+\cs_new:Npn \@@_change_case_next_end:nnn #1#2#3
+ { \@@_change_case_skip:nnw {#2} {#3} }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -853,6 +869,13 @@
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \begin{macro}{\text_declare_case_equivalent:Nn}
% Create equivalents to allow replacement.
@@ -914,6 +937,7 @@
{
\tl_clear_new:c { l_@@_ #2 case _ #1 _ #3 _tl }
\tl_set:cn { l_@@_ #2 case _ #1 _ #3 _ tl } {#4}
+ \tl_clear_new:c { l_@@_ #2 case_special_ #3 _tl }
}
% \end{macrocode}
% \end{macro}
@@ -944,55 +968,58 @@
% \end{macro}
%
% \begin{macro}[EXP]
-% {\@@_change_case_upper_de-x-eszett:nnnn, \@@_change_case_upper_de-alt:nnnn}
+% {
+% \@@_change_case_upper_de-x-eszett:nnnnn,
+% \@@_change_case_upper_de-alt:nnnnn
+% }
% A simple alternative version for German.
% \begin{macrocode}
-\cs_new:cpn { @@_change_case_upper_de-x-eszett:nnnn } #1#2#3#4
+\cs_new:cpn { @@_change_case_upper_de-x-eszett:nnnnn } #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "00DF }
+ \@@_codepoint_compare:nNnTF {#5} = { "00DF }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "1E9E }
- { \@@_change_case_catcode:nn {#4} { "1E9E } }
+ { \@@_change_case_catcode:nn {#5} { "1E9E } }
}
- \use:c { @@_change_case_next_ #2 :nn }
- {#2} {#3}
+ \use:c { @@_change_case_next_ #2 :nnn }
+ {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
-\cs_new_eq:cc { @@_change_case_upper_de-alt:nnnn }
- { @@_change_case_upper_de-x-eszett:nnnn }
+\cs_new_eq:cc { @@_change_case_upper_de-alt:nnnnn }
+ { @@_change_case_upper_de-x-eszett:nnnnn }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
% {
-% \@@_change_case_upper_el:nnnn ,
-% \@@_change_case_upper_el_aux:nnnn ,
-% \@@_change_case_upper_el-x-iota:nnnn
+% \@@_change_case_upper_el:nnnnn ,
+% \@@_change_case_upper_el-x-iota:nnnnn ,
+% \@@_change_case_upper_el_aux:nnnnn
% }
-% \begin{macro}[EXP]{\@@_change_case_upper_el:nnn}
-% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnw}
+% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_upper_el:nnnnw}
% \begin{macro}[EXP]
-% {\@@_change_case_upper_el:nnnN, \@@_change_case_upper_el_aux:nnnN}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnw}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnN}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnn}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_dialytika:nnn}
+% {\@@_change_case_upper_el:nnnnN, \@@_change_case_upper_el_aux:nnnnN}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnnw}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnnN}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_ypogegrammeni:nnnnnnn}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_dialytika:nnnn}
% \begin{macro}[EXP]{\@@_change_case_upper_el_dialytika:n}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnnw}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnnN}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnnnw}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnnnN}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_hiatus:nnnnn}
% \begin{macro}[EXP]
% {
% \@@_change_case_upper_el_ypogegrammeni:n ,
% \@@_change_case_upper_el-x-iota_ypogegrammeni:n
% }
% \begin{macro}[EXP]{\@@_change_case_upper_el_stress:nn}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnw}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnN}
-% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnn}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnnw}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_upper_el_gobble:nnnn}
% \begin{macro}[EXP,noTF]
% {
% \@@_change_case_if_greek:n ,
@@ -1017,65 +1044,65 @@
% for \pdfTeX{} so is best left unchanged, and the latter has issues concerning
% how \texttt{LGR} outputs the input and output (differently!).
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_el:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_el:nnnnn #1#2#3#4#5
{
\bool_lazy_and:nnTF
- { \@@_change_case_if_greek_p:n {#4} }
+ { \@@_change_case_if_greek_p:n {#5} }
{
! \bool_lazy_or_p:nn
- { \@@_codepoint_compare_p:nNn {#4} = { "0374 } }
- { \@@_codepoint_compare_p:nNn {#4} = { "037E } }
+ { \@@_codepoint_compare_p:nNn {#5} = { "0374 } }
+ { \@@_codepoint_compare_p:nNn {#5} = { "037E } }
}
{
- \@@_change_case_if_greek_spacing_diacritic:nTF {#4}
+ \@@_change_case_if_greek_spacing_diacritic:nTF {#5}
{
- \@@_change_case_store:n {#4}
- \@@_change_case_loop:nnw
+ \@@_change_case_store:n {#5}
+ \@@_change_case_loop:nnnw
}
{
- \exp_args:Ne \@@_change_case_upper_el:nnn
+ \exp_args:Ne \@@_change_case_upper_el:nnnn
{
\codepoint_to_nfd:n
- { \@@_codepoint_from_chars:Nw #4 }
+ { \@@_codepoint_from_chars:Nw #5 }
}
}
- {#2} {#3}
+ {#2} {#3} {#4}
}
{
- \@@_codepoint_compare:nNnTF {#4} = { "0345 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0345 }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0399 }
{ \char_value_catcode:n { "0399 } }
}
- \@@_change_case_loop:nnw {#2} {#3}
+ \@@_change_case_loop:nnnw {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
}
-\cs_new_eq:cN { @@_change_case_upper_el-x-iota:nnnn }
- \@@_change_case_upper_el:nnnn
-\cs_new:Npn \@@_change_case_upper_el:nnn #1#2#3
+\cs_new_eq:cN { @@_change_case_upper_el-x-iota:nnnnn }
+ \@@_change_case_upper_el:nnnnn
+\cs_new:Npn \@@_change_case_upper_el:nnnn #1#2#3#4
{
\@@_codepoint_process:nN
- { \@@_change_case_upper_el:nnnw {#2} {#3} } #1
+ { \@@_change_case_upper_el:nnnnw {#2} {#3} {#4} } #1
}
% \end{macrocode}
% At this stage we have the first NFD codepoint as |#3|. What we need to know
% is whether after that we have another character, either from the NFD or
% directly in the input. If not, we store the changed character at this stage.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_el:nnnw #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_upper_el:nnnnw #1#2#3#4#5 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_upper_el:nnnN {#3} }
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_upper_el:nnnnN {#4} }
{
\@@_change_case_store:e
- { \@@_change_case_codepoint:nn { upper } {#3} }
- \@@_change_case_loop:nnw
+ { \@@_change_case_codepoint:nn { upper } {#4} }
+ \@@_change_case_loop:nnnw
}
- {#1} {#2} #4 \q_@@_recursion_stop
+ {#1} {#2} {#3} #5 \q_@@_recursion_stop
}
% \end{macrocode}
% Now, we check the detail of the next codepoint: again we filter out the
@@ -1085,99 +1112,99 @@
% to move any ypogegrammeni to after accents (in case the input is not
% normalised). The ypogegrammeni itself is handled separately.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_el:nnnN #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_el:nnnnN #1#2#3#4#5
{
- \token_if_cs:NTF #4
+ \token_if_cs:NTF #5
{
\@@_change_case_store:e
{ \@@_change_case_codepoint:nn { upper } {#1} }
- \@@_change_case_loop:nnw {#2} {#3} #4
+ \@@_change_case_loop:nnnw {#2} {#3} {#4} #5
}
{
\@@_change_case_if_takes_ypogegrammeni:nTF {#1}
{
- \@@_change_case_upper_el_ypogegrammeni:nnnnnw
- {#1} {#2} {#3} { } { } #4
+ \@@_change_case_upper_el_ypogegrammeni:nnnnnnw
+ {#1} {#2} {#3} {#4} { } { } #5
}
- { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4 }
+ { \@@_change_case_upper_el_aux:nnnnN {#1} {#2} {#3} {#4} #5 }
}
}
-\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnw
- #1#2#3#4#5#6 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnnw
+ #1#2#3#4#5#6#7 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#6}
+ \tl_if_head_is_N_type:nTF {#7}
{
- \@@_change_case_upper_el_ypogegrammeni:nnnnnN
- {#1} {#2} {#3} {#4} {#5}
+ \@@_change_case_upper_el_ypogegrammeni:nnnnnnN
+ {#1} {#2} {#3} {#4} {#5} {#6}
}
- { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4#5 }
- #6 \q_@@_recursion_stop
+ { \@@_change_case_upper_el_aux:nnnnN {#1} {#2} {#3} {#4} #5#6 }
+ #7 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnN #1#2#3#4#5#6
+\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnnN #1#2#3#4#5#6#7
{
- \token_if_cs:NTF #6
- { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4#5 }
+ \token_if_cs:NTF #7
+ { \@@_change_case_upper_el_aux:nnnnN {#1} {#2} {#3} {#4} #5#6 }
{
\@@_codepoint_process:nN
{
- \@@_change_case_upper_el_ypogegrammeni:nnnnnn
- {#1} {#2} {#3} {#4} {#5}
+ \@@_change_case_upper_el_ypogegrammeni:nnnnnnn
+ {#1} {#2} {#3} {#4} {#5} {#6}
}
}
- #6
+ #7
}
-\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnn #1#2#3#4#5#6
+\cs_new:Npn \@@_change_case_upper_el_ypogegrammeni:nnnnnnn #1#2#3#4#5#6#7
{
- \@@_codepoint_compare:nNnTF {#6} = { "0345 }
+ \@@_codepoint_compare:nNnTF {#7} = { "0345 }
{
- \@@_change_case_upper_el_ypogegrammeni:nnnnnw
- {#1} {#2} {#3} {#4} {#6}
+ \@@_change_case_upper_el_ypogegrammeni:nnnnnnw
+ {#1} {#2} {#3} {#4} {#5} {#7}
}
{
\bool_lazy_or:nnTF
- { \@@_change_case_if_greek_accent_p:n {#6} }
- { \@@_change_case_if_greek_breathing_p:n {#6} }
+ { \@@_change_case_if_greek_accent_p:n {#7} }
+ { \@@_change_case_if_greek_breathing_p:n {#7} }
{
- \@@_change_case_upper_el_ypogegrammeni:nnnnnw
- {#1} {#2} {#3} {#4#6} {#5}
+ \@@_change_case_upper_el_ypogegrammeni:nnnnnnw
+ {#1} {#2} {#3} {#4} {#5#7} {#6}
}
- { \@@_change_case_upper_el_aux:nnnN {#1} {#2} {#3} #4#5 #6 }
+ { \@@_change_case_upper_el_aux:nnnnN {#1} {#2} {#3} {#4} #5#6 #7 }
}
}
-\cs_new:Npn \@@_change_case_upper_el_aux:nnnN #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_el_aux:nnnnN #1#2#3#4#5
{
\@@_codepoint_process:nN
- { \@@_change_case_upper_el_aux:nnnn {#1} {#2} {#3} } #4
+ { \@@_change_case_upper_el_aux:nnnnn {#1} {#2} {#3} {#4} } #5
}
-\cs_new:Npn \@@_change_case_upper_el_aux:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_el_aux:nnnnn #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "0308 }
- { \@@_change_case_upper_el_dialytika:nnn {#2} {#3} {#1} }
+ \@@_codepoint_compare:nNnTF {#5} = { "0308 }
+ { \@@_change_case_upper_el_dialytika:nnnn {#2} {#3} {#4} {#1} }
{
- \@@_change_case_if_greek_accent:nTF {#4}
- { \@@_change_case_upper_el_hiatus:nnnw {#2} {#3} {#1} }
+ \@@_change_case_if_greek_accent:nTF {#5}
+ { \@@_change_case_upper_el_hiatus:nnnnw {#2} {#3} {#4} {#1} }
{
- \@@_change_case_if_greek_breathing:nTF {#4}
- { \@@_change_case_upper_el:nnn {#1} {#2} {#3} }
+ \@@_change_case_if_greek_breathing:nTF {#5}
+ { \@@_change_case_upper_el:nnnn {#1} {#2} {#3} {#4} }
{
- \@@_codepoint_compare:nNnTF {#4} = { "0345 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0345 }
{
\@@_change_case_store:e
- { \use:c { @@_change_case_upper_ #3 _ypogegrammeni:n } {#1} }
- \@@_change_case_loop:nnw {#2} {#3}
+ { \use:c { @@_change_case_upper_ #4 _ypogegrammeni:n } {#1} }
+ \@@_change_case_loop:nnnw {#2} {#3} {#4}
}
{
- \@@_change_case_if_greek_stress:nTF {#4}
+ \@@_change_case_if_greek_stress:nTF {#5}
{
\@@_change_case_store:e
- { \@@_change_case_upper_el_stress:nn {#1} {#4} }
- \@@_change_case_loop:nnw {#2} {#3}
+ { \@@_change_case_upper_el_stress:nn {#1} {#5} }
+ \@@_change_case_loop:nnnw {#2} {#3} {#4}
}
{
\@@_change_case_store:e
{ \@@_change_case_codepoint:nn { upper } {#1} }
- \@@_change_case_loop:nnw {#2} {#3} #4
+ \@@_change_case_loop:nnnw {#2} {#3} {#4} #5
}
}
}
@@ -1189,15 +1216,15 @@
% We know only two letters take it, so we can shortcut here on the second
% part of the tests.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_el_dialytika:nnn #1#2#3
+\cs_new:Npn \@@_change_case_upper_el_dialytika:nnnn #1#2#3#4
{
- \@@_change_case_if_takes_dialytika:nTF {#3}
- { \@@_change_case_upper_el_dialytika:n {#3} }
+ \@@_change_case_if_takes_dialytika:nTF {#4}
+ { \@@_change_case_upper_el_dialytika:n {#4} }
{
\@@_change_case_store:e
- { \@@_change_case_codepoint:nn { upper } {#3} }
+ { \@@_change_case_codepoint:nn { upper } {#4} }
}
- \@@_change_case_upper_el_gobble:nnw {#1} {#2}
+ \@@_change_case_upper_el_gobble:nnnw {#1} {#2} {#3}
}
\cs_new:Npn \@@_change_case_upper_el_dialytika:n #1
{
@@ -1220,41 +1247,41 @@
% Adding a hiatus needs some of the same ideas, but if there is not one we
% skip this code point, hence needing a separate function.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_el_hiatus:nnnw
- #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_upper_el_hiatus:nnnnw
+ #1#2#3#4#5 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_upper_el_hiatus:nnnN {#3} }
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_upper_el_hiatus:nnnnN {#4} }
{
\@@_change_case_store:e
- { \@@_change_case_codepoint:nn { upper } {#3} }
- \@@_change_case_loop:nnw
+ { \@@_change_case_codepoint:nn { upper } {#4} }
+ \@@_change_case_loop:nnnw
}
- {#1} {#2} #4 \q_@@_recursion_stop
+ {#1} {#2} {#3} #5 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_upper_el_hiatus:nnnN #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_el_hiatus:nnnnN #1#2#3#4#5
{
- \token_if_cs:NTF #4
+ \token_if_cs:NTF #5
{
\@@_change_case_store:e
{ \@@_change_case_codepoint:nn { upper } {#1} }
- \@@_change_case_loop:nnw {#2} {#3} #4
+ \@@_change_case_loop:nnnw {#2} {#3} {#4} #5
}
{
\@@_codepoint_process:nN
- { \@@_change_case_upper_el_hiatus:nnnn {#1} {#2} {#3} } #4
+ { \@@_change_case_upper_el_hiatus:nnnnn {#1} {#2} {#3} {#4} } #5
}
}
-\cs_new:Npn \@@_change_case_upper_el_hiatus:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_el_hiatus:nnnnn #1#2#3#4#5
{
- \@@_change_case_if_takes_dialytika:nTF {#4}
+ \@@_change_case_if_takes_dialytika:nTF {#5}
{
\@@_change_case_store:e
{ \@@_change_case_codepoint:nn { upper } {#1} }
- \@@_change_case_upper_el_dialytika:n {#4}
- \@@_change_case_upper_el_gobble:nnw {#2} {#3}
+ \@@_change_case_upper_el_dialytika:n {#5}
+ \@@_change_case_upper_el_gobble:nnnw {#2} {#3} {#4}
}
- { \@@_change_case_upper_el:nnn {#1} {#2} {#3} #4 }
+ { \@@_change_case_upper_el:nnnn {#1} {#2} {#3} {#4} #5 }
}
% \end{macrocode}
% Handling the \emph{ypogegrammeni} output depends on the selected approach
@@ -1323,31 +1350,31 @@
% For clearing out trailing combining marks after we have dealt with
% the first one.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_el_gobble:nnw
- #1#2#3 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_upper_el_gobble:nnnw
+ #1#2#3#4 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_change_case_upper_el_gobble:nnN }
- { \@@_change_case_loop:nnw }
- {#1} {#2} #3 \q_@@_recursion_stop
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_change_case_upper_el_gobble:nnnN }
+ { \@@_change_case_loop:nnnw }
+ {#1} {#2} {#3} #4 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_upper_el_gobble:nnN #1#2#3
+\cs_new:Npn \@@_change_case_upper_el_gobble:nnnN #1#2#3#4
{
- \token_if_cs:NTF #3
- { \@@_change_case_loop:nnw {#1} {#2} }
+ \token_if_cs:NTF #4
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} }
{
\@@_codepoint_process:nN
- { \@@_change_case_upper_el_gobble:nnn {#1} {#2} }
+ { \@@_change_case_upper_el_gobble:nnnn {#1} {#2} {#3} }
}
- #3
+ #4
}
-\cs_new:Npn \@@_change_case_upper_el_gobble:nnn #1#2#3
+\cs_new:Npn \@@_change_case_upper_el_gobble:nnnn #1#2#3#4
{
\bool_lazy_or:nnTF
- { \@@_change_case_if_greek_accent_p:n {#3} }
- { \@@_change_case_if_greek_breathing_p:n {#3} }
- { \@@_change_case_upper_el_gobble:nnw {#1} {#2} }
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ { \@@_change_case_if_greek_accent_p:n {#4} }
+ { \@@_change_case_if_greek_breathing_p:n {#4} }
+ { \@@_change_case_upper_el_gobble:nnnw {#1} {#2} {#3} }
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} #4 }
}
% \end{macrocode}
% Luckily the Greek range is limited and clear.
@@ -1597,98 +1624,101 @@
% \end{macro}
% \end{macro}
% \begin{macro}[EXP]
-% {\@@_change_case_boundary_upper_el:Nnnw, \@@_change_case_boundary_upper_el-x-iota:Nnnw}
-% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnN}
-% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnn}
-% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnnw}
+% {
+% \@@_change_case_boundary_upper_el:Nnnnw,
+% \@@_change_case_boundary_upper_el-x-iota:Nnnnw
+% }
+% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_boundary_upper_el:nnnnw}
% There is one things that need special treatment at start start of
% words in Greek. For an isolated accent \emph{eta},
% which is handled by seeing if we have exactly one of the affected
% codepoints followed by a space or brace group.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_boundary_upper_el:Nnnw
- #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_boundary_upper_el:Nnnnw
+ #1#2#3#4#5 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_boundary_upper_el:nnN }
- { \@@_change_case_loop:nnw }
- {#2} {#3} #4 \q_@@_recursion_stop
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_boundary_upper_el:nnnN }
+ { \@@_change_case_loop:nnnw }
+ {#2} {#3} {#4} #5 \q_@@_recursion_stop
}
-\cs_new_eq:cN { @@_change_case_boundary_upper_el-x-iota:Nnnw }
- \@@_change_case_boundary_upper_el:Nnnw
-\cs_new:Npn \@@_change_case_boundary_upper_el:nnN #1#2#3
+\cs_new_eq:cN { @@_change_case_boundary_upper_el-x-iota:Nnnnw }
+ \@@_change_case_boundary_upper_el:Nnnnw
+\cs_new:Npn \@@_change_case_boundary_upper_el:nnnN #1#2#3#4
{
- \token_if_cs:NTF #3
- { \@@_change_case_loop:nnw {#1} {#2} }
+ \token_if_cs:NTF #4
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} }
{
\@@_codepoint_process:nN
- { \@@_change_case_boundary_upper_el:nnn {#1} {#2} }
+ { \@@_change_case_boundary_upper_el:nnnn {#1} {#2} {#3} }
}
- #3
+ #4
}
-\cs_new:Npn \@@_change_case_boundary_upper_el:nnn #1#2#3
+\cs_new:Npn \@@_change_case_boundary_upper_el:nnnn #1#2#3#4
{
\bool_lazy_any:nTF
{
- { \@@_codepoint_compare_p:nNn {#3} = { "0389 } }
- { \@@_codepoint_compare_p:nNn {#3} = { "03AE } }
- { \@@_codepoint_compare_p:nNn {#3} = { "1F22 } }
- { \@@_codepoint_compare_p:nNn {#3} = { "1F2A } }
+ { \@@_codepoint_compare_p:nNn {#4} = { "0389 } }
+ { \@@_codepoint_compare_p:nNn {#4} = { "03AE } }
+ { \@@_codepoint_compare_p:nNn {#4} = { "1F22 } }
+ { \@@_codepoint_compare_p:nNn {#4} = { "1F2A } }
}
- { \@@_change_case_boundary_upper_el:nnnw {#1} {#2} {#3} }
- { \@@_change_case_breathing:nnn {#1} {#2} {#3} }
+ { \@@_change_case_boundary_upper_el:nnnnw {#1} {#2} {#3} {#4} }
+ { \@@_change_case_breathing:nnnn {#1} {#2} {#3} {#4} }
}
-\cs_new:Npn \@@_change_case_boundary_upper_el:nnnw
- #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_boundary_upper_el:nnnnw
+ #1#2#3#4#5 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} #4 }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0389 }
- { \@@_change_case_catcode:nn {#3} { "0389 } }
+ { \@@_change_case_catcode:nn {#4} { "0389 } }
}
- \@@_change_case_loop:nnw {#1} {#2}
+ \@@_change_case_loop:nnnw {#1} {#2} {#3}
}
- #4 \q_@@_recursion_stop
+ #5 \q_@@_recursion_stop
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
-% \begin{macro}[EXP]{\@@_change_case_breathing:nnn}
% \begin{macro}[EXP]{\@@_change_case_breathing:nnnn}
-% \begin{macro}[EXP]{\@@_change_case_breathing:nnnnw}
+% \begin{macro}[EXP]{\@@_change_case_breathing:nnnnn}
% \begin{macro}[EXP]{\@@_change_case_breathing:nnnnnw}
-% \begin{macro}[EXP]{\@@_change_case_breathing_aux:nnnnn}
-% \begin{macro}[EXP]{\@@_change_case_breathing_aux:nnnw}
-% \begin{macro}[EXP]{\@@_change_case_breathing_aux:nnN}
-% \begin{macro}[EXP]{\@@_change_case_breathing_dialytika:nnn}
+% \begin{macro}[EXP]{\@@_change_case_breathing:nnnnnnw}
+% \begin{macro}[EXP]{\@@_change_case_breathing_aux:nnnnnn}
+% \begin{macro}[EXP]{\@@_change_case_breathing_aux:nnnnw}
+% \begin{macro}[EXP]{\@@_change_case_breathing_aux:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_breathing_dialytika:nnnn}
% In Greek, breathing diacritics are normally dropped when uppercasing:
% see the code for the general case. However, for the first character
% of a word, if there is a breather \emph{and} the next character takes
% a \emph{dialytika}, it needs to be added. We start by checking if
% the current codepoint is in the Greek range, then decomposing.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_breathing:nnn #1#2#3
+\cs_new:Npn \@@_change_case_breathing:nnnn #1#2#3#4
{
- \@@_change_case_if_greek:nTF {#3}
+ \@@_change_case_if_greek:nTF {#4}
{
- \exp_args:Ne \@@_change_case_breathing:nnnn
+ \exp_args:Ne \@@_change_case_breathing:nnnnn
{
\codepoint_to_nfd:n
- { \@@_codepoint_from_chars:Nw #3 }
+ { \@@_codepoint_from_chars:Nw #4 }
}
- {#1} {#2} {#3}
+ {#1} {#2} {#3} {#4}
}
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} #4 }
}
-\cs_new:Npn \@@_change_case_breathing:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_breathing:nnnnn #1#2#3#4#5
{
\@@_codepoint_process:nN
- { \@@_change_case_breathing:nnnnw {#2} {#3} {#4} }
+ { \@@_change_case_breathing:nnnnnw {#2} {#3} {#4} {#5} }
#1 \q_mark
}
% \end{macrocode}
@@ -1699,36 +1729,36 @@
% and second if the final resulting codepoint is one of the two we
% care about.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_breathing:nnnnw #1#2#3#4#5 \q_mark
+\cs_new:Npn \@@_change_case_breathing:nnnnnw #1#2#3#4#5#6 \q_mark
{
- \tl_if_blank:nTF {#5}
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ \tl_if_blank:nTF {#6}
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} #4 }
{
\@@_codepoint_process:nN
- { \@@_change_case_breathing:nnnnnw {#1} {#2} {#3} {#4} }
- #5 \q_mark
+ { \@@_change_case_breathing:nnnnnnw {#1} {#2} {#3} {#4} {#5} }
+ #6 \q_mark
}
}
-\cs_new:Npn \@@_change_case_breathing:nnnnnw #1#2#3#4#5#6 \q_mark
+\cs_new:Npn \@@_change_case_breathing:nnnnnnw #1#2#3#4#5#6#7 \q_mark
{
- \tl_if_blank:nTF {#6}
+ \tl_if_blank:nTF {#7}
{
- \@@_change_case_breathing_aux:nnnnn
- {#1} {#2} {#3} {#4} {#5}
+ \@@_change_case_breathing_aux:nnnnnn
+ {#1} {#2} {#3} {#4} {#5} {#6}
}
{
\@@_codepoint_process:nN
- { \@@_change_case_breathing:nnnnnw {#1} {#2} {#3} {#4} }
- #6 \q_mark
+ { \@@_change_case_breathing:nnnnnnw {#1} {#2} {#3} {#4} {#5} }
+ #7 \q_mark
}
}
-\cs_new:Npn \@@_change_case_breathing_aux:nnnnn #1#2#3#4#5
+\cs_new:Npn \@@_change_case_breathing_aux:nnnnnn #1#2#3#4#5#6
{
\bool_lazy_or:nnTF
- { \@@_codepoint_compare_p:nNn {#5} = { "0313 } }
- { \@@_codepoint_compare_p:nNn {#5} = { "0314 } }
- { \@@_change_case_breathing_aux:nnnw {#1} {#2} {#4} }
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ { \@@_codepoint_compare_p:nNn {#6} = { "0313 } }
+ { \@@_codepoint_compare_p:nNn {#6} = { "0314 } }
+ { \@@_change_case_breathing_aux:nnnnw {#1} {#2} {#3} {#5} }
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} #4 }
}
% \end{macrocode}
% Now the lookahead can be fired: check the next codepoint and assess
@@ -1736,29 +1766,29 @@
% breathing mark or generate the \emph{dialytika}: the
% latter is code shared with the general mechanism.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_breathing_aux:nnnw #1#2#3#4
+\cs_new:Npn \@@_change_case_breathing_aux:nnnnw #1#2#3#4#5
\q_@@_recursion_stop
{
\@@_change_case_store:e
- { \@@_change_case_codepoint:nn { upper } {#3} }
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_breathing_aux:nnN }
- { \@@_change_case_loop:nnw }
- {#1} {#2} #4 \q_@@_recursion_stop
+ { \@@_change_case_codepoint:nn { upper } {#4} }
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_breathing_aux:nnnN }
+ { \@@_change_case_loop:nnnw }
+ {#1} {#2} {#3} #5 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_breathing_aux:nnN #1#2#3
+\cs_new:Npn \@@_change_case_breathing_aux:nnnN #1#2#3#4
{
\@@_codepoint_process:nN
- { \@@_change_case_breathing_dialytika:nnn {#1} {#2} } #3
+ { \@@_change_case_breathing_dialytika:nnnn {#1} {#2} {#3} } #4
}
-\cs_new:Npn \@@_change_case_breathing_dialytika:nnn #1#2#3
+\cs_new:Npn \@@_change_case_breathing_dialytika:nnnn #1#2#3#4
{
- \@@_change_case_if_takes_dialytika:nTF {#3}
+ \@@_change_case_if_takes_dialytika:nTF {#4}
{
- \@@_change_case_upper_el_dialytika:n {#3}
- \@@_change_case_loop:nnw {#1} {#2}
+ \@@_change_case_upper_el_dialytika:n {#4}
+ \@@_change_case_loop:nnnw {#1} {#2} {#3}
}
- { \@@_change_case_loop:nnw {#1} {#2} #3 }
+ { \@@_change_case_loop:nnnw {#1} {#2} {#3} #4 }
}
% \end{macrocode}
% \end{macro}
@@ -1769,88 +1799,88 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \begin{macro}[EXP]{\@@_change_case_title_el:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_title_el:nnnnn}
% Titlecasing retains accents, but to prevent the uppercasing code
% from kicking in, there has to be an explicit function here.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_title_el:nnnn #1#2#3#4
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+\cs_new:Npn \@@_change_case_title_el:nnnnn #1#2#3#4#5
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
% {
-% \@@_change_case_upper_hy:nnnn ,
-% \@@_change_case_title_hy:nnnn ,
-% \@@_change_case_upper_hy-x-yiwn:nnnn ,
-% \@@_change_case_title_hy-x-yiwn:nnnn
+% \@@_change_case_upper_hy:nnnnn ,
+% \@@_change_case_title_hy:nnnnn ,
+% \@@_change_case_upper_hy-x-yiwn:nnnnn ,
+% \@@_change_case_title_hy-x-yiwn:nnnnn
% }
% See \url{https://www.unicode.org/L2/L2020/20143-armenian-ech-yiwn.pdf}.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_hy:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_hy:nnnnn #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "0587 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0587 }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0535 }
- { \@@_change_case_catcode:nn {#4} { "0535 } }
+ { \@@_change_case_catcode:nn {#5} { "0535 } }
\codepoint_generate:nn { "054E }
- { \@@_change_case_catcode:nn {#4} { "054E } }
+ { \@@_change_case_catcode:nn {#5} { "054E } }
}
- \use:c { @@_change_case_next_ #2 :nn }
- {#2} {#3}
+ \use:c { @@_change_case_next_ #2 :nnn }
+ {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
-\cs_new:Npn \@@_change_case_title_hy:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_title_hy:nnnnn #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "0587 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0587 }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0535 }
- { \@@_change_case_catcode:nn {#4} { "0535 } }
+ { \@@_change_case_catcode:nn {#5} { "0535 } }
\codepoint_generate:nn { "057E }
- { \@@_change_case_catcode:nn {#4} { "057E } }
+ { \@@_change_case_catcode:nn {#5} { "057E } }
}
- \use:c { @@_change_case_next_ #2 :nn }
- {#2} {#3}
+ \use:c { @@_change_case_next_ #2 :nnn }
+ {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
-\cs_new:cpn { @@_change_case_upper_hy-x-yiwn:nnnn } #1#2#3#4
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
-\cs_new_eq:cc { @@_change_case_title_hy-x-yiwn:nnnn }
- { @@_change_case_upper_hy-x-yiwn:nnnn }
+\cs_new:cpn { @@_change_case_upper_hy-x-yiwn:nnnnn } #1#2#3#4#5
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
+\cs_new_eq:cc { @@_change_case_title_hy-x-yiwn:nnnnn }
+ { @@_change_case_upper_hy-x-yiwn:nnnnn }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP]{\@@_change_case_lower_la-x-medieval:nnnn}
-% \begin{macro}[EXP]{\@@_change_case_upper_la-x-medieval:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_lower_la-x-medieval:nnnnn}
+% \begin{macro}[EXP]{\@@_change_case_upper_la-x-medieval:nnnnn}
% Simply swaps of characters.
% \begin{macrocode}
-\cs_new:cpn { @@_change_case_lower_la-x-medieval:nnnn } #1#2#3#4
+\cs_new:cpn { @@_change_case_lower_la-x-medieval:nnnnn } #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "0056 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0056 }
{
\@@_change_case_store:e
- { \char_generate:nn { "0075 } { \@@_char_catcode:N #4 } }
- \use:c { @@_change_case_next_ #2 :nn }
- {#2} {#3}
+ { \char_generate:nn { "0075 } { \@@_char_catcode:N #5 } }
+ \use:c { @@_change_case_next_ #2 :nnn }
+ {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
-\cs_new:cpn { @@_change_case_upper_la-x-medieval:nnnn } #1#2#3#4
+\cs_new:cpn { @@_change_case_upper_la-x-medieval:nnnnn } #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "0075 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0075 }
{
\@@_change_case_store:e
- { \char_generate:nn { "0056 } { \@@_char_catcode:N #4 } }
- \use:c { @@_change_case_next_ #2 :nn }
- {#2} {#3}
+ { \char_generate:nn { "0056 } { \@@_char_catcode:N #5 } }
+ \use:c { @@_change_case_next_ #2 :nnn }
+ {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
% \end{macrocode}
% \end{macro}
@@ -1858,62 +1888,62 @@
%
% \begin{macro}[EXP]
% {
-% \@@_change_cases_lower_lt:nnnn ,
-% \@@_change_cases_lower_lt_auxi:nnnn ,
-% \@@_change_cases_lower_lt_auxii:nnnn
+% \@@_change_cases_lower_lt:nnnnn ,
+% \@@_change_cases_lower_lt_auxi:nnnnn ,
+% \@@_change_cases_lower_lt_auxii:nnnnn
% }
-% \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnw}
-% \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnN}
-% \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnn}
+% \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnnw}
+% \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnnN}
+% \begin{macro}[rEXP]{\@@_change_case_lower_lt:nnnn}
% For Lithuanian, the issue to be dealt with is dots over lower case
% letters: these should be present if there is another accent. The first step
% is a simple match attempt: look for the three uppercase accented letters
% which should gain a dot-above char in their lowercase form.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_lower_lt:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_lt:nnnnn #1#2#3#4#5
{
- \exp_args:Ne \@@_change_case_lower_lt_auxi:nnnn
+ \exp_args:Ne \@@_change_case_lower_lt_auxi:nnnnn
{
- \int_case:nn { \@@_codepoint_from_chars:Nw #4 }
+ \int_case:nn { \@@_codepoint_from_chars:Nw #5 }
{
{ "00CC } { "0300 }
{ "00CD } { "0301 }
{ "0128 } { "0303 }
}
}
- {#2} {#3} {#4}
+ {#2} {#3} {#4} {#5}
}
% \end{macrocode}
% If there was a hit, output the result with the dot-above and move on.
% Otherwise, look for one of the three letters that can take a combining
% accent: I, J nd I-ogonek.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_lower_lt_auxi:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_lt_auxi:nnnnn #1#2#3#4#5
{
\tl_if_blank:nTF {#1}
{
- \exp_args:Ne \@@_change_case_lower_lt_auxii:nnnn
+ \exp_args:Ne \@@_change_case_lower_lt_auxii:nnnnn
{
- \int_case:nn { \@@_codepoint_from_chars:Nw #4 }
+ \int_case:nn { \@@_codepoint_from_chars:Nw #5 }
{
{ "0049 } { "0069 }
{ "004A } { "006A }
{ "012E } { "012F }
}
}
- {#2} {#3} {#4}
+ {#2} {#3} {#4} {#5}
}
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0069 }
- { \@@_change_case_catcode:nn {#4} { "0069 } }
+ { \@@_change_case_catcode:nn {#5} { "0069 } }
\codepoint_generate:nn { "0307 }
- { \@@_change_case_catcode:nn {#4} { "0307 } }
+ { \@@_change_case_catcode:nn {#5} { "0307 } }
\codepoint_generate:nn {#1}
- { \@@_change_case_catcode:nn {#4} {#1} }
+ { \@@_change_case_catcode:nn {#5} {#1} }
}
- \@@_change_case_loop:nnw {#2} {#3}
+ \@@_change_case_loop:nnnw {#2} {#3} {#4}
}
}
% \end{macrocode}
@@ -1921,55 +1951,55 @@
% then need to look for a combining accent: as usual, we need to be aware of
% the loop situation.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_lower_lt_auxii:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_lt_auxii:nnnnn #1#2#3#4#5
{
\tl_if_blank:nTF {#1}
- { \@@_change_case_codepoint:nnnn {#2} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#2} {#2} {#3} {#4} {#5} }
{
\@@_change_case_store:e
{
\codepoint_generate:nn {#1}
- { \@@_change_case_catcode:nn {#4} {#1} }
+ { \@@_change_case_catcode:nn {#5} {#1} }
}
- \@@_change_case_lower_lt:nnw {#2} {#3}
+ \@@_change_case_lower_lt:nnnw {#2} {#3} {#4}
}
}
-\cs_new:Npn \@@_change_case_lower_lt:nnw #1#2#3 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_lower_lt:nnnw #1#2#3#4 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_change_case_lower_lt:nnN }
- { \@@_change_case_loop:nnw }
- {#1} {#2} #3 \q_@@_recursion_stop
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_change_case_lower_lt:nnnN }
+ { \@@_change_case_loop:nnnw }
+ {#1} {#2} {#3} #4 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_lower_lt:nnN #1#2#3
+\cs_new:Npn \@@_change_case_lower_lt:nnnN #1#2#3#4
{
\@@_codepoint_process:nN
- { \@@_change_case_lower_lt:nnn {#1} {#2} } #3
+ { \@@_change_case_lower_lt:nnnn {#1} {#2} {#3} } #4
}
-\cs_new:Npn \@@_change_case_lower_lt:nnn #1#2#3
+\cs_new:Npn \@@_change_case_lower_lt:nnnn #1#2#3#4
{
\bool_lazy_and:nnT
{
\bool_lazy_or_p:nn
- { ! \tl_if_single_p:n {#3} }
- { ! \token_if_cs_p:N #3 }
+ { ! \tl_if_single_p:n {#4} }
+ { ! \token_if_cs_p:N #4 }
}
{
\bool_lazy_any_p:n
{
- { \@@_codepoint_compare_p:nNn {#3} = { "0300 } }
- { \@@_codepoint_compare_p:nNn {#3} = { "0301 } }
- { \@@_codepoint_compare_p:nNn {#3} = { "0303 } }
+ { \@@_codepoint_compare_p:nNn {#4} = { "0300 } }
+ { \@@_codepoint_compare_p:nNn {#4} = { "0301 } }
+ { \@@_codepoint_compare_p:nNn {#4} = { "0303 } }
}
}
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0307 }
- { \@@_change_case_catcode:nn {#3} { "0307 } }
+ { \@@_change_case_catcode:nn {#4} { "0307 } }
}
}
- \@@_change_case_loop:nnw {#1} {#2} #3
+ \@@_change_case_loop:nnnw {#1} {#2} {#3} #4
}
% \end{macrocode}
% \end{macro}
@@ -1978,64 +2008,64 @@
% \end{macro}
% \begin{macro}[EXP]
% {
-% \@@_change_cases_upper_lt:nnnn ,
-% \@@_change_cases_upper_lt_aux:nnnn
+% \@@_change_cases_upper_lt:nnnnn ,
+% \@@_change_cases_upper_lt_aux:nnnnn
% }
-% \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnw}
-% \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnN}
-% \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnn}
+% \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnnw}
+% \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnnN}
+% \begin{macro}[rEXP]{\@@_change_case_upper_lt:nnnn}
% The uppercasing version: first find i/j/i-ogonek, then look for the
% combining char: drop it if present.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_lt:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_lt:nnnnn #1#2#3#4#5
{
- \exp_args:Ne \@@_change_case_upper_lt_aux:nnnn
+ \exp_args:Ne \@@_change_case_upper_lt_aux:nnnnn
{
- \int_case:nn { \@@_codepoint_from_chars:Nw #4 }
+ \int_case:nn { \@@_codepoint_from_chars:Nw #5 }
{
{ "0069 } { "0049 }
{ "006A } { "004A }
{ "012F } { "012E }
}
}
- {#2} {#3} {#4}
+ {#2} {#3} {#4} {#5}
}
-\cs_new:Npn \@@_change_case_upper_lt_aux:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_lt_aux:nnnnn #1#2#3#4#5
{
\tl_if_blank:nTF {#1}
- { \@@_change_case_codepoint:nnnn { upper } {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn { upper } {#2} {#3} {#4} {#5} }
{
\@@_change_case_store:e
{
\codepoint_generate:nn {#1}
- { \@@_change_case_catcode:nn {#4} {#1} }
+ { \@@_change_case_catcode:nn {#5} {#1} }
}
- \@@_change_case_upper_lt:nnw {#2} {#3}
+ \@@_change_case_upper_lt:nnnw {#2} {#3} {#4}
}
}
-\cs_new:Npn \@@_change_case_upper_lt:nnw #1#2#3 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_upper_lt:nnnw #1#2#3#4 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_change_case_upper_lt:nnN }
- { \use:c { @@_change_case_next_ #1 :nn } }
- {#1} {#2} #3 \q_@@_recursion_stop
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_change_case_upper_lt:nnnN }
+ { \use:c { @@_change_case_next_ #1 :nnn } }
+ {#1} {#2} {#3} #4 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_upper_lt:nnN #1#2#3
+\cs_new:Npn \@@_change_case_upper_lt:nnnN #1#2#3#4
{
\@@_codepoint_process:nN
- { \@@_change_case_upper_lt:nnn {#1} {#2} } #3
+ { \@@_change_case_upper_lt:nnnn {#1} {#2} {#3} } #4
}
-\cs_new:Npn \@@_change_case_upper_lt:nnn #1#2#3
+\cs_new:Npn \@@_change_case_upper_lt:nnnn #1#2#3#4
{
\bool_lazy_and:nnTF
{
\bool_lazy_or_p:nn
- { ! \tl_if_single_p:n {#3} }
- { ! \token_if_cs_p:N #3 }
+ { ! \tl_if_single_p:n {#4} }
+ { ! \token_if_cs_p:N #4 }
}
- { \@@_codepoint_compare_p:nNn {#3} = { "0307 } }
- { \use:c { @@_change_case_next_ #1 :nn } {#1} {#2} }
- { \use:c { @@_change_case_next_ #1 :nn } {#1} {#2} #3 }
+ { \@@_codepoint_compare_p:nNn {#4} = { "0307 } }
+ { \use:c { @@_change_case_next_ #1 :nnn } {#1} {#2} {#3} }
+ { \use:c { @@_change_case_next_ #1 :nnn } {#1} {#2} {#3} #4 }
}
% \end{macrocode}
% \end{macro}
@@ -2044,84 +2074,84 @@
% \end{macro}
%
% \begin{macro}[EXP]
-% {\@@_change_case_title_nl:nnnn, \@@_change_case_title_nl_aux:nnnn}
-% \begin{macro}[EXP]{\@@_change_case_title_nl:nnw}
-% \begin{macro}[EXP]{\@@_change_case_title_nl:nnN}
+% {\@@_change_case_title_nl:nnnnn, \@@_change_case_title_nl_aux:nnnnn}
+% \begin{macro}[EXP]{\@@_change_case_title_nl:nnnw}
+% \begin{macro}[EXP]{\@@_change_case_title_nl:nnnN}
% For Dutch, there is a single look-ahead test for \texttt{ij} when
% title casing. If the appropriate letters are found, produce \texttt{IJ}
% and gobble the \texttt{j}/\texttt{J}.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_title_nl:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_title_nl:nnnnn #1#2#3#4#5
{
- \tl_if_single:nTF {#4}
- { \@@_change_case_title_nl_aux:nnnn }
- { \@@_change_case_codepoint:nnnn }
- {#1} {#2} {#3} {#4}
+ \tl_if_single:nTF {#5}
+ { \@@_change_case_title_nl_aux:nnnnn }
+ { \@@_change_case_codepoint:nnnnn }
+ {#1} {#2} {#3} {#4} {#5}
}
-\cs_new:Npn \@@_change_case_title_nl_aux:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_title_nl_aux:nnnnn #1#2#3#4#5
{
\bool_lazy_or:nnTF
- { \int_compare_p:nNn {`#4} = { "0049 } }
- { \int_compare_p:nNn {`#4} = { "0069 } }
+ { \int_compare_p:nNn {`#5} = { "0049 } }
+ { \int_compare_p:nNn {`#5} = { "0069 } }
{
\@@_change_case_store:e
- { \char_generate:nn { "0049 } { \@@_char_catcode:N #4 } }
- \@@_change_case_title_nl:nnw {#2} {#3}
+ { \char_generate:nn { "0049 } { \@@_char_catcode:N #5 } }
+ \@@_change_case_title_nl:nnnw {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
-\cs_new:Npn \@@_change_case_title_nl:nnw #1#2#3 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_title_nl:nnnw #1#2#3#4 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#3}
- { \@@_change_case_title_nl:nnN }
- { \use:c { @@_change_case_next_ #1 :nn } }
- {#1} {#2} #3 \q_@@_recursion_stop
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_change_case_title_nl:nnnN }
+ { \use:c { @@_change_case_next_ #1 :nnn } }
+ {#1} {#2} {#3} #4 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_title_nl:nnN #1#2#3
+\cs_new:Npn \@@_change_case_title_nl:nnnN #1#2#3#4
{
\bool_lazy_and:nnTF
- { ! \token_if_cs_p:N #3 }
+ { ! \token_if_cs_p:N #4 }
{
\bool_lazy_or_p:nn
- { \int_compare_p:nNn {`#3} = { "004A } }
- { \int_compare_p:nNn {`#3} = { "006A } }
+ { \int_compare_p:nNn {`#4} = { "004A } }
+ { \int_compare_p:nNn {`#4} = { "006A } }
}
{
\@@_change_case_store:e
- { \char_generate:nn { "004A } { \@@_char_catcode:N #3 } }
- \use:c { @@_change_case_next_ #1 :nn } {#1} {#2}
+ { \char_generate:nn { "004A } { \@@_char_catcode:N #4 } }
+ \use:c { @@_change_case_next_ #1 :nnn } {#1} {#2} {#3}
}
- { \use:c { @@_change_case_next_ #1 :nn } {#1} {#2} #3 }
+ { \use:c { @@_change_case_next_ #1 :nnn } {#1} {#2} {#3} #4 }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP]{\@@_change_case_lower_tr:nnnn}
-% \begin{macro}[EXP]{\@@_change_case_lower_tr:nnNw}
-% \begin{macro}[EXP]{\@@_change_case_lower_tr:NnnN}
-% \begin{macro}[EXP]{\@@_change_case_lower_tr:Nnnn}
+% \begin{macro}[EXP]{\@@_change_case_lower_tr:nnnnn}
+% \begin{macro}[EXP]{\@@_change_case_lower_tr:nnnNw}
+% \begin{macro}[EXP]{\@@_change_case_lower_tr:NnnnN}
+% \begin{macro}[EXP]{\@@_change_case_lower_tr:Nnnnn}
% The Turkic languages need special treatment for dotted-i and dotless-i.
% The lower casing rule can be expressed in terms of searching first for
% either a dotless-I or a dotted-I. In the latter case the mapping is
% easy, but in the former there is a second stage search.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_lower_tr:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_tr:nnnnn #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "0049 }
- { \@@_change_case_lower_tr:nnNw {#1} {#3} #4 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0049 }
+ { \@@_change_case_lower_tr:nnnNw {#1} {#3} {#4} #5 }
{
- \@@_codepoint_compare:nNnTF {#4} = { "0130 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0130 }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0069 }
- { \@@_change_case_catcode:nn {#4} { "0069 } }
+ { \@@_change_case_catcode:nn {#5} { "0069 } }
}
- \@@_change_case_loop:nnw {#1} {#3}
+ \@@_change_case_loop:nnnw {#1} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
}
% \end{macrocode}
@@ -2130,41 +2160,41 @@
% combination is found both the dotless-I and the dot-above char have to
% be removed from the input.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_lower_tr:nnNw #1#2#3#4 \q_@@_recursion_stop
+\cs_new:Npn \@@_change_case_lower_tr:nnnNw #1#2#3#4#5 \q_@@_recursion_stop
{
- \tl_if_head_is_N_type:nTF {#4}
- { \@@_change_case_lower_tr:NnnN #3 {#1} {#2} }
+ \tl_if_head_is_N_type:nTF {#5}
+ { \@@_change_case_lower_tr:NnnnN #4 {#1} {#2} {#3} }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0131 }
- { \@@_change_case_catcode:nn {#3} { "0131 } }
+ { \@@_change_case_catcode:nn {#4} { "0131 } }
}
- \@@_change_case_loop:nnw {#1} {#2}
+ \@@_change_case_loop:nnnw {#1} {#2} {#3}
}
- #4 \q_@@_recursion_stop
+ #5 \q_@@_recursion_stop
}
-\cs_new:Npn \@@_change_case_lower_tr:NnnN #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_tr:NnnnN #1#2#3#4#5
{
\@@_codepoint_process:nN
- { \@@_change_case_lower_tr:Nnnn #1 {#2} {#3} } #4
+ { \@@_change_case_lower_tr:Nnnnn #1 {#2} {#3} {#4} } #5
}
-\cs_new:Npn \@@_change_case_lower_tr:Nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_lower_tr:Nnnnn #1#2#3#4#5
{
\bool_lazy_or:nnTF
{
\bool_lazy_and_p:nn
- { \tl_if_single_p:n {#4} }
- { \token_if_cs_p:N #4 }
+ { \tl_if_single_p:n {#5} }
+ { \token_if_cs_p:N #5 }
}
- { ! \@@_codepoint_compare_p:nNn {#4} = { "0307 } }
+ { ! \@@_codepoint_compare_p:nNn {#5} = { "0307 } }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0131 }
{ \@@_change_case_catcode:nn {#1} { "0131 } }
}
- \@@_change_case_loop:nnw {#2} {#3} #4
+ \@@_change_case_loop:nnnw {#2} {#3} {#4} #5
}
{
\@@_change_case_store:e
@@ -2172,7 +2202,7 @@
\codepoint_generate:nn { "0069 }
{ \@@_change_case_catcode:nn {#1} { "0069 } }
}
- \@@_change_case_loop:nnw {#2} {#3}
+ \@@_change_case_loop:nnnw {#2} {#3} {#4}
}
}
% \end{macrocode}
@@ -2180,33 +2210,33 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \begin{macro}[EXP]{\@@_change_case_upper_tr:nnnn}
+% \begin{macro}[EXP]{\@@_change_case_upper_tr:nnnnn}
% Uppercasing is easier: just one exception with no context.
% \begin{macrocode}
-\cs_new:Npn \@@_change_case_upper_tr:nnnn #1#2#3#4
+\cs_new:Npn \@@_change_case_upper_tr:nnnnn #1#2#3#4#5
{
- \@@_codepoint_compare:nNnTF {#4} = { "0069 }
+ \@@_codepoint_compare:nNnTF {#5} = { "0069 }
{
\@@_change_case_store:e
{
\codepoint_generate:nn { "0130 }
- { \@@_change_case_catcode:nn {#4} { "0130 } }
+ { \@@_change_case_catcode:nn {#5} { "0130 } }
}
- \use:c { @@_change_case_next_ #2 :nn } {#2} {#3}
+ \use:c { @@_change_case_next_ #2 :nnn } {#2} {#3} {#4}
}
- { \@@_change_case_codepoint:nnnn {#1} {#2} {#3} {#4} }
+ { \@@_change_case_codepoint:nnnnn {#1} {#2} {#3} {#4} {#5} }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
-% {\@@_change_case_lower_az:nnnn, \@@_change_case_upper_az:nnnn}
+% {\@@_change_case_lower_az:nnnnn, \@@_change_case_upper_az:nnnnn}
% Straight copies.
% \begin{macrocode}
-\cs_new_eq:NN \@@_change_case_lower_az:nnnn
- \@@_change_case_lower_tr:nnnn
-\cs_new_eq:NN \@@_change_case_upper_az:nnnn
- \@@_change_case_upper_tr:nnnn
+\cs_new_eq:NN \@@_change_case_lower_az:nnnnn
+ \@@_change_case_lower_tr:nnnnn
+\cs_new_eq:NN \@@_change_case_upper_az:nnnnn
+ \@@_change_case_upper_tr:nnnnn
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx
index 8b3ac6098c5..d863e51acef 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx
@@ -2,7 +2,7 @@
%
%% File: l3text-map.dtx
%
-% Copyright (C) 2022,2023 The LaTeX Project
+% Copyright (C) 2022-2023 The LaTeX Project
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
index 075b3707379..5770853cd72 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
index 8df534cc84a..ea33b588557 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -94,18 +94,18 @@
%
% \section{Case changing}
%
-% \begin{function}[EXP, added = 2019-11-20, updated = 2022-10-13]
+% \begin{function}[EXP, added = 2019-11-20, updated = 2023-07-08]
% {
-% \text_lowercase:n, \text_uppercase:n, \text_titlecase:n,
+% \text_lowercase:n, \text_uppercase:n, \text_titlecase_all:n,
% \text_titlecase_first:n,
-% \text_lowercase:nn, \text_uppercase:nn, \text_titlecase:nn,
+% \text_lowercase:nn, \text_uppercase:nn, \text_titlecase_all:nn,
% \text_titlecase_first:nn
% }
% \begin{syntax}
% \cs{text_uppercase:n} \Arg{tokens}
% \cs{text_uppercase:nn} \Arg{BCP-47} \Arg{tokens}
% \end{syntax}
-% Takes user input \meta{text} first applies \cs{text_expand}, then
+% Takes user input \meta{text} first applies \cs{text_expand:n}, then
% transforms the case of character tokens as specified by the
% function name. The category code of letters are not changed by this
% process when Unicode engines are used; in $8$-bit engines, case changed
@@ -115,11 +115,13 @@
%
% Upper- and lowercase have the obvious meanings. Titlecasing may be regarded
% informally as converting the first character of the \meta{tokens} to
-% uppercase and the rest to lowercase. However, the process is more complex
+% uppercase. However, the process is more complex
% than this as there are some situations where a single lowercase character
% maps to a special form, for example \texttt{ij} in Dutch which becomes
-% \texttt{IJ}. The \texttt{titlecase_first} variant does not attempt
-% any case changing at all after the first letter has been processed.
+% \texttt{IJ}. There are two functions available for titlecasing: one which
+% applies the change to each \enquote{word} and a second which only applies
+% at the start of the input. (Here, \enquote{word} boundaries are spaces:
+% at present, full Unicode word breaking is not attempted.)
%
% Importantly, notice that these functions are intended for working with
% user \emph{text for typesetting}. For case changing programmatic data see
@@ -163,10 +165,7 @@
% I-dot and introduced when upper casing i-dotless.
% \item German (\texttt{de-x-eszett}).
% An alternative mapping for German in which the lowercase
-% \emph{Eszett} maps to a \emph{gro\ss{}es Eszett}. Since there is
-% a |T1| slot for the \emph{gro\ss{}es Eszett} in |T1|, this
-% tailoring \emph{is} available with \pdfTeX{} as well as in the
-% Unicode \TeX{} engines.
+% \emph{Eszett} maps to a \emph{gro\ss{}es Eszett}.
% \item Greek (\texttt{el}).
% Removes accents from Greek letters when uppercasing; titlecasing
% leaves accents in place. A variant \texttt{el-x-iota} is available
@@ -185,25 +184,17 @@
% The characters |u| and |V| are interchanged on case changing.
% \item Dutch (\texttt{nl}).
% Capitalisation of \texttt{ij} at the beginning of titlecased
-% input produces \texttt{IJ} rather than \texttt{Ij}. The output
-% retains two separate letters, thus this transformation \emph{is}
-% available using \pdfTeX{}.
+% input produces \texttt{IJ} rather than \texttt{Ij}.
% \end{itemize}
%
-% For titlecasing, note that there are two functions available. The
-% function \cs{text_titlecase:n} applies (broadly) uppercasing to the first
-% letter of the input, then lowercasing to the remainder. In contrast,
-% \cs{text_titlecase_first:n} \emph{only} carries out the uppercasing operation,
-% and leaves the balance of the input unchanged. Determining whether
-% non-letter characters at the start of text should switch from upper- to
-% lowercasing is controllable. When \cs{l_text_titlecase_check_letter_bool} is
+% Determining whether non-letter characters at the start of text should count
+% as the uppercase element is controllable. When \cs{l_text_titlecase_check_letter_bool} is
% \texttt{true}, characters which are not letters (category code~$11$) are
-% left unchanged and \enquote{skipped}: the first \emph{letter} is uppercased.
+% \enquote{skipped}: the first \emph{letter} is uppercased.
% (With $8$-bit engines, this is extended to active characters which form
% part of a multi-byte letter codepoint.) When
% \cs{l_text_titlecase_check_letter_bool} is \texttt{false}, the first
-% character is uppercased, and the rest lowercased, irrespective of the nature
-% of the character.
+% character is uppercased, irrespective of the category code of the character.
%
% \begin{function}[added = 2022-07-04]
% {
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
index 9cadf04e878..6336b0d0765 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -177,9 +177,6 @@
% by avoiding \cs{exp_not:n} for characters other than active and macro
% parameters.)
%
-% ^^A todo: ask LuaTeX list for an \ifx\undefined <active char>
-% ^^A which does not add the <active char> in memory.
-%
% \begin{macrocode}
%<*package>
% \end{macrocode}
@@ -443,6 +440,42 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_analysis_disable_char:N}
+% Similar to \cs{@@_analysis_disable:n}, but it receives a normal
+% character token, tests if that token is active (by turning it into
+% a space: the active space has been undefined at this point), and
+% if so, disables it. Even if the character is active and set equal
+% to a primitive conditional, nothing blows up.
+% Again, in \pTeX{} and \upTeX{} we skip characters beyond $[0,255]$,
+% which cannot be active anyways.
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_active:N \^^@
+ \cs_new_protected:Npn \@@_analysis_disable_char:N #1
+ {
+ \tex_lccode:D `#1 = 32 \exp_stop_f:
+ \tex_lowercase:D { \if_meaning:w #1 } \tex_undefined:D
+ \tex_let:D #1 \tex_undefined:D
+ \fi:
+ }
+ \bool_lazy_or:nnT
+ { \sys_if_engine_ptex_p: }
+ { \sys_if_engine_uptex_p: }
+ {
+ \cs_gset_protected:Npn \@@_analysis_disable_char:N #1
+ {
+ \if_int_compare:w 256 > `#1 \exp_stop_f:
+ \tex_lccode:D `#1 = 32 \exp_stop_f:
+ \tex_lowercase:D { \if_meaning:w #1 } \tex_undefined:D
+ \tex_let:D #1 \tex_undefined:D
+ \fi:
+ \fi:
+ }
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+%
% \subsection{First pass}
%
% The goal of this pass is to detect special (non-\texttt{N}-type) tokens,
@@ -737,7 +770,7 @@
\exp_after:wN \use_ii:nn
\fi:
{
- \@@_analysis_disable:n { `#1 }
+ \@@_analysis_disable_char:N #1
\int_incr:N \l_@@_analysis_normal_int
}
{ \@@_analysis_cs_space_count:NN \@@_analysis_a_cs:ww #1 }
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
index e606c3c5587..f3c52e2a0f0 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -187,7 +187,7 @@
% \tl_put_left:co,
% \tl_gput_left:Nn, \tl_gput_left:NV, \tl_gput_left:Nv, \tl_gput_left:Ne,
% \tl_gput_left:No,
-% \tl_gput_left:cn, \tl_gput_left:cV, \tl_gput_left:cv, \tl_gput_left:ce
+% \tl_gput_left:cn, \tl_gput_left:cV, \tl_gput_left:cv, \tl_gput_left:ce,
% \tl_gput_left:co
% }
% \begin{syntax}
@@ -205,7 +205,7 @@
% \tl_put_right:co,
% \tl_gput_right:Nn, \tl_gput_right:NV, \tl_gput_right:Nv, \tl_gput_right:Ne,
% \tl_gput_right:No,
-% \tl_gput_right:cn, \tl_gput_right:cV, \tl_gput_right:cv, \tl_gput_right:ce
+% \tl_gput_right:cn, \tl_gput_right:cV, \tl_gput_right:cv, \tl_gput_right:ce,
% \tl_gput_right:co
% }
% \begin{syntax}
@@ -592,8 +592,8 @@
% \begin{syntax}
% \cs{tl_reverse_items:n} \Arg{token list}
% \end{syntax}
-% Reverses the order of the \meta{items} stored in \meta{tl~var},
-% so that \Arg{item_1}\Arg{item_2}\Arg{item_3} \ldots \Arg{item_n}
+% Reverses the order of the \meta{items} in the \meta{token list},
+% so that \meta{item_1}\meta{item_2}\meta{item_3} \ldots \meta{item_n}
% becomes \Arg{item_n} \ldots{} \Arg{item_3}\Arg{item_2}\Arg{item_1}.
% This process removes any unprotected space within the
% \meta{token list}. Braced token groups are copied without
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
index aedde780987..888ceb36012 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%
@@ -481,6 +481,18 @@
% \end{texnote}
% \end{function}
%
+% \begin{function}[EXP,added = 2023-10-15]{\token_to_catcode:N}
+% \begin{syntax}
+% \cs{token_to_catcode:N} \meta{token}
+% \end{syntax}
+% Converts the given \meta{token} into a number describing its category code.
+% If \meta{token} is a control sequence this expands to $16$. This can't
+% detect the categories $0$ (escape character), $5$ (end of line), $9$
+% (ignored character), $14$ (comment character), or $15$ (invalid character).
+% Control sequences or active characters let to a token of one of the
+% detectable category codes will yield that category.
+% \end{function}
+%
% \section{Token conditionals}
%
% \begin{function}[EXP,pTF]{\token_if_group_begin:N}
@@ -1022,7 +1034,7 @@
% For instance \cs{peek_regex:nTF} \verb"{ abc | [a-z] }" |{ } { }|
% |abc| will only inspect the first token~|a| even though the first
% branch |abc| of the alternative is preferred in functions such as
-% \cs{peek_regex_remove_once:n}. This may have an effect on
+% \cs{peek_regex_remove_once:nTF}. This may have an effect on
% tokenization if the input stream has not yet been tokenized and
% category codes are changed.
% \end{texnote}
@@ -1221,7 +1233,7 @@
% \end{syntax}
% Converts the \meta{char} to the equivalent case-changed character
% as detailed by the function name (see \cs{str_foldcase:n}
-% and \cs{text_titlecase:n} for details of these terms). The case mapping
+% and \cs{text_titlecase_all:n} for details of these terms). The case mapping
% is carried out with no context-dependence (\emph{cf.}~\cs{text_uppercase:n},
% \emph{etc.}) The \texttt{str} versions always generate \enquote{other}
% (category code $12$) characters, whilst the standard versions generate
@@ -1873,6 +1885,66 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\token_to_catcode:N}
+% \begin{macro}{\@@_to_catcode:N}
+% The macro works by comparing the input token with \cs{if_catcode:w} with all
+% valid category codes. Since the most common tokens in an average argument
+% list are of category $11$ or $12$ those are tested first. And since a space
+% and braces are no ordinary |N|-type arguments, and only control sequences
+% let to those categories can match them they are tested last.
+% \begin{macrocode}
+\cs_new:Npn \token_to_catcode:N
+ { \int_value:w \group_align_safe_begin: \@@_to_catcode:N }
+\cs_new:Npn \@@_to_catcode:N #1
+ {
+ \if_catcode:w \exp_not:N #1 \c_catcode_letter_token
+ 11
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_catcode_other_token
+ 12
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_math_toggle_token
+ 3
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_alignment_token
+ 4
+ \else:
+ \if_catcode:w \exp_not:N #1 ##
+ 6
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_math_superscript_token
+ 7
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_math_subscript_token
+ 8
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_group_begin_token
+ 1
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_group_end_token
+ 2
+ \else:
+ \if_catcode:w \exp_not:N #1 \c_space_token
+ 10
+ \else:
+ \token_if_cs:NTF #1 { 16 } { 13 }
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ \group_align_safe_end:
+ \exp_stop_f:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}
% {
% \c_group_begin_token,
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
index 2161e0963ef..54486cc0faf 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2023-10-10}
+% \date{Released 2023-10-23}
%
% \maketitle
%