summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2022-08-31 20:19:45 +0000
committerKarl Berry <karl@freefriends.org>2022-08-31 20:19:45 +0000
commitdda31e626ef6f0f11d9fc942ef8feb6025acd8af (patch)
tree92adcb154d72f7f045e7286a71c8d4ae8741881c /Master
parentd07f71d9e3f85f6a7703ffaa7dfdba4281750aa6 (diff)
l3kernel (31aug22)
git-svn-id: svn://tug.org/texlive/trunk@64251 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md14
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/README.md2
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/expl3.pdfbin626173 -> 626173 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/interface3.pdfbin1770652 -> 1776937 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/interface3.tex2
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3doc.pdfbin557782 -> 557782 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdfbin151820 -> 151820 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news.pdfbin395879 -> 395879 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news01.pdfbin122710 -> 122710 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news02.pdfbin150676 -> 150676 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news03.pdfbin148702 -> 148702 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news04.pdfbin114588 -> 114588 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news05.pdfbin112487 -> 112487 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news06.pdfbin151573 -> 151573 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news07.pdfbin128309 -> 128309 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news08.pdfbin163454 -> 163454 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news09.pdfbin250139 -> 250139 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news10.pdfbin150279 -> 150279 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news11.pdfbin170063 -> 170063 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3news12.pdfbin204990 -> 204990 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdfbin81567 -> 81567 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdfbin296239 -> 296240 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex2
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdfbin242906 -> 242905 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex2
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdfbin231316 -> 231316 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex2
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/source3.pdfbin7258705 -> 7320159 bytes
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/source3.tex2
-rw-r--r--Master/texmf-dist/doc/latex/l3kernel/source3body.tex1
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/expl3.dtx4
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3.ins1
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3basics.dtx2
-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.dtx20
-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.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3debug.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3doc.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx2
-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.dtx2
-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-logic.dtx2
-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-traps.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3int.dtx2
-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.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx2
-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.dtx140
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prg.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prop.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3quark.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3regex.dtx2
-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.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3sys.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx36
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx586
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3text.dtx178
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3token.dtx113
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx346
-rw-r--r--Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex881
-rw-r--r--Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex2
-rw-r--r--Master/texmf-dist/tex/latex/l3kernel/expl3.ltx2
-rw-r--r--Master/texmf-dist/tex/latex/l3kernel/expl3.sty2
92 files changed, 2054 insertions, 382 deletions
diff --git a/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md b/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
index d747679ef0e..90ed2a87712 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
+++ b/Master/texmf-dist/doc/latex/l3kernel/CHANGELOG.md
@@ -7,6 +7,17 @@ this project uses date-based 'snapshot' version identifiers.
## [Unreleased]
+## [2022-08-30]
+
+### Added
+- `\pdf_object_new:n` and `\pdf_object_write:nnn` - support assignment of object
+ type at point-of-writing (issue
+ [\#1123](https://github.com/latex3/latex3/issues/1123))
+- `\text_map_function:nN` and `\text_map_inline:nn` for mapping to
+ graphemes in textual input
+- Support for medevial Latin case changing
+- `\char_to_nfd:n` to extend NFD support to 8-bit engines
+
## [2022-08-23]
### Added
@@ -1188,7 +1199,8 @@ this project uses date-based 'snapshot' version identifiers.
- Step functions have been added for dim variables,
e.g. `\dim_step_inline:nnnn`
-[Unreleased]: https://github.com/latex3/latex3/compare/2022-08-23...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2022-08-30...HEAD
+[2022-08-30]: https://github.com/latex3/latex3/compare/2022-08-23...2022-08-30
[2022-08-23]: https://github.com/latex3/latex3/compare/2022-08-05...2022-08-23
[2022-08-05]: https://github.com/latex3/latex3/compare/2022-07-15...2022-08-05
[2022-07-15]: https://github.com/latex3/latex3/compare/2022-07-14...2022-07-15
diff --git a/Master/texmf-dist/doc/latex/l3kernel/README.md b/Master/texmf-dist/doc/latex/l3kernel/README.md
index f25e9207e6d..b6538e1855b 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/README.md
+++ b/Master/texmf-dist/doc/latex/l3kernel/README.md
@@ -1,7 +1,7 @@
LaTeX3 Programming Conventions
==============================
-Release 2022-08-23
+Release 2022-08-30
Overview
--------
diff --git a/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf b/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
index c86280538e4..57266100418 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/expl3.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf b/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
index c16be2ce98f..99e424d0c3e 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/interface3.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/interface3.tex b/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
index 528adb8e9d4..64d4cff5615 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
+++ b/Master/texmf-dist/doc/latex/l3kernel/interface3.tex
@@ -54,7 +54,7 @@ for those people who are interested.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2022-08-23}
+\date{Released 2022-08-30}
\pagenumbering{roman}
\maketitle
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3doc.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3doc.pdf
index ed15603bb86..115b0155b92 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3doc.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3doc.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
index e95341e2c85..492c003636c 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3docstrip.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
index ff974735f18..11ac8695c2e 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
index d6af6a94e5e..23221ecb1f8 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news01.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
index 3b9fb3e2333..8443ef58022 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news02.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
index 1ed36a25863..b085e342324 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news03.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
index 3f38bc64e1d..223cf692816 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news04.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
index 27f25062b41..17dac20b2c1 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news05.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
index 1522296e77d..b8514e2cc33 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news06.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
index 1d7e8d46db7..753717acd7d 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news07.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
index 9817c2739e7..136b9e6c8ab 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news08.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
index 728d25b06b0..83f867b7f0f 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news09.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
index 07e6da0ac57..99341027da9 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news10.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
index 241f98de949..dc636b1ddb8 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news11.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
index 8b8859834ad..07aeb8ed1fa 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3news12.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
index bc82e9425ad..7aebfbe9bc5 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3prefixes.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
index f198f8d2254..3a082655fd2 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
index 81cc5e13473..c7352e8c42f 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3styleguide.tex
@@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2022-08-23}
+\date{Released 2022-08-30}
\begin{document}
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
index eed70fbe059..459cdc2b017 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
index 4afd7aac057..83cca7ef05f 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3syntax-changes.tex
@@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2022-08-23}
+\date{Released 2022-08-30}
\newcommand{\TF}{\textit{(TF)}}
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
index 8fb11d26d25..b940dadaf55 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
index e45a40cd7b6..a4d96e41647 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
+++ b/Master/texmf-dist/doc/latex/l3kernel/l3term-glossary.tex
@@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2022-08-23}
+\date{Released 2022-08-30}
\newcommand{\TF}{\textit{(TF)}}
diff --git a/Master/texmf-dist/doc/latex/l3kernel/source3.pdf b/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
index 3d3159d3966..d262f0d76fd 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
+++ b/Master/texmf-dist/doc/latex/l3kernel/source3.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/l3kernel/source3.tex b/Master/texmf-dist/doc/latex/l3kernel/source3.tex
index 587253a1e3a..090cb477859 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/source3.tex
+++ b/Master/texmf-dist/doc/latex/l3kernel/source3.tex
@@ -53,7 +53,7 @@ for those people who are interested.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2022-08-23}
+\date{Released 2022-08-30}
\pagenumbering{roman}
\maketitle
diff --git a/Master/texmf-dist/doc/latex/l3kernel/source3body.tex b/Master/texmf-dist/doc/latex/l3kernel/source3body.tex
index 20e1875361e..c9b0f3448da 100644
--- a/Master/texmf-dist/doc/latex/l3kernel/source3body.tex
+++ b/Master/texmf-dist/doc/latex/l3kernel/source3body.tex
@@ -589,6 +589,7 @@ used on top of \LaTeXe{} if \cs{outer} tokens are used in the arguments.
\clist_gput_right:Nn \g_docinput_clist
{
l3text-case.dtx ,
+ l3text-map.dtx ,
l3text-purify.dtx
}
\ExplSyntaxOff
diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
index 63f43014382..ebf703b25fa 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{2022-08-23}%
+\def\ExplFileDate{2022-08-30}%
%<*driver>
\documentclass[full]{l3doc}
\usepackage{graphicx}
@@ -51,7 +51,7 @@
% }^^A
% }
%
-% \date{Released 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3.ins b/Master/texmf-dist/source/latex/l3kernel/l3.ins
index fbcc815d9f0..08949c097e8 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3.ins
+++ b/Master/texmf-dist/source/latex/l3kernel/l3.ins
@@ -106,6 +106,7 @@ and all files in that bundle must be distributed together.
\from{l3unicode.dtx} {package}
\from{l3text.dtx} {package}
\from{l3text-case.dtx} {package}
+ \from{l3text-map.dtx} {package}
\from{l3text-purify.dtx}{package}
\from{l3candidates.dtx} {package}
\from{l3legacy.dtx} {package}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
index 69a59f065be..b881dbcf1d6 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
index 43a666d3ce8..963aae5ddbb 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
index 67767992eef..bc0fbb7eb59 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
index 155d51bc0e9..3279dda7629 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
@@ -643,9 +643,21 @@
% \cs{char_to_nfd:N} \meta{char}
% \end{syntax}
% Converts the \meta{char} to the Unicode Normalization Form Canonical
-% Decomposition. The category code of the generated character is the
-% same as the \meta{char}. With $8$-bit engines, no change is made to the
-% character.
+% Decomposition. The category code of the \emph{first} generated character is
+% the same as the \meta{char}; second and subsequent chars will have the
+% current category code, as they would if typed in directly. For $8$-bit
+% engines, no change will take place.
+% \end{function}
+%
+% \begin{function}[added = 2022-08-29, rEXP]{\char_to_nfd:n}
+% \begin{syntax}
+% \cs{char_to_nfd:n} \Arg{codepoint}
+% \end{syntax}
+% Converts the (Unicode) \meta{codepoint} to the Unicode Normalization
+% Form Canonical Decomposition. The generated character(s) will have
+% the current category code as they would if typed in directly. In contrast
+% to \cs{char_to_nfd:N}, this function \emph{does} decompose codepoints
+% with $8$-bit engines.
% \end{function}
%
% \begin{function}[added = 2018-09-23]
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx b/Master/texmf-dist/source/latex/l3kernel/l3cctab.dtx
index fac045495c4..6bc41991e51 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
index 34e78c62a35..4814d90427e 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
index 7d822312ebf..ded70d1248f 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
index 33b28721edf..08b4f523e00 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx b/Master/texmf-dist/source/latex/l3kernel/l3debug.dtx
index 9fe0518b1f9..4867d5f5632 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx b/Master/texmf-dist/source/latex/l3kernel/l3deprecation.dtx
index 4153116c3a3..ef7d77d064f 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
index d8b2dc92548..6fdf2e694f1 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 2022-08-23}
+% \date{Released 2022-08-30}
% \maketitle
% \tableofcontents
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
index bbf456084c1..b7dc2c22573 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
@@ -63,7 +63,7 @@
% }^^A
% }
%
-% \date{Released 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
index 71b45cc3cab..e975071462f 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
index 642f77afde6..7aaf7085de8 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx b/Master/texmf-dist/source/latex/l3kernel/l3flag.dtx
index af66b619641..cbe5351708f 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
index 66e5be677de..8fa46b49dd3 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 2022-08-23}
+% \date{Released 2022-08-30}
% \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 4b16b7c6fca..63c97ba5c15 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
index 9afe96a0695..74bd289d7ad 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
index daa67ea0a13..f39b77b9ee3 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
index ed26025368d..ca6d5091c75 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
index bc7e1770937..b24112a5a0c 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
index dbade2f5901..6fb84bfb97d 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
index efe9a6dfe92..facb50f0ea0 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-random.dtx
index 4cd51f0f893..ae5b968ecaf 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
index 1a56d98509b..f6122647e9c 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
index b566e3d1bb8..1f0fbfa6a89 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
@@ -40,7 +40,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2022-08-23}
+% \date{Released 2022-08-30}
% \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 a45b7856ff5..f19a864aab2 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
index 8d7c44dd352..da64860f8c5 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fparray.dtx
index c41a991af53..293154cad00 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
index 1a6cb9ba77c..7fce0b7a2d1 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx b/Master/texmf-dist/source/latex/l3kernel/l3intarray.dtx
index 5e49b94d4ef..be1fe6f7e31 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx b/Master/texmf-dist/source/latex/l3kernel/l3kernel-functions.dtx
index c26a6f0ccf1..d122477aeb7 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
index d8313614d12..f626c9bdb25 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx b/Master/texmf-dist/source/latex/l3kernel/l3legacy.dtx
index dc92bba1b5a..3d37094612d 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
index de35da4d948..bb5779f09eb 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
index 8c9ac087e8f..32f66edd92e 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
index ce1ec1a49de..5566ead50cf 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx b/Master/texmf-dist/source/latex/l3kernel/l3pdf.dtx
index 5a28010dde3..f02362df387 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
@@ -51,32 +51,18 @@
%
% \section{Objects}
%
-% \begin{function}[added = 2021-02-10]{\pdf_object_new:nn}
-% \begin{syntax}
-% \cs{pdf_object_new:nn} \Arg{object} \Arg{type}
-% \end{syntax}
-% Declares \meta{object} as a PDF object of \meta{type}, which should be
-% one of
-% \begin{itemize}
-% \item \texttt{array}
-% \item \texttt{dict}
-% \item \texttt{fstream}
-% \item \texttt{stream}
-% \end{itemize}
-% The object may be referenced from this point on, and written later
-% using \cs{pdf_object_write:nn}.
-% \end{function}
-% \begin{function}[EXP, pTF, added=2020-05-15]{\pdf_object_if_exist:n}
+% \begin{function}[added = 2022-08-23]{\pdf_object_new:n}
% \begin{syntax}
-% \cs{pdf_object_if_exist_p:n} \Arg{object}
-% \cs{pdf_object_if_exist:nTF} \Arg{object}
+% \cs{pdf_object_new:n} \Arg{object}
% \end{syntax}
-% Tests whether an object with name \Arg{object} has been defined.
+% Declares \meta{object} as a PDF object. The object may be referenced
+% from this point on, and written later using \cs{pdf_object_write:nnn}.
% \end{function}
-% \begin{function}[added = 2021-02-10]
-% {\pdf_object_write:nn, \pdf_object_write:nx}
+%
+% \begin{function}[added = 2022-08-23]
+% {\pdf_object_write:nnn, \pdf_object_write:nnx}
% \begin{syntax}
-% \cs{pdf_object_write:nn} \Arg{object} \Arg{content}
+% \cs{pdf_object_write:nn} \Arg{object} \Arg{type} \Arg{content}
% \end{syntax}
% Writes the \meta{content} as content of the \meta{object}. Depending on the
% \meta{type} declared for the object, the format required for the
@@ -133,6 +119,14 @@
% Inserts the appropriate information to reference the \meta{pageobject}.
% \end{function}
%
+% \begin{function}[EXP, pTF, added = 2020-05-15]{\pdf_object_if_exist:n}
+% \begin{syntax}
+% \cs{pdf_object_if_exist_p:n} \Arg{object}
+% \cs{pdf_object_if_exist:nTF} \Arg{object}
+% \end{syntax}
+% Tests whether an object with name \Arg{object} has been defined.
+% \end{function}
+%
% \section{Version}
%
% \begin{function}[pTF, EXP, added = 2021-02-10]{\pdf_version_compare:Nn}
@@ -250,6 +244,46 @@
% \end{function}
% \end{documentation}
%
+% \section{Deprecated functions}
+%
+% \begin{function}[added = 2021-02-10]{\pdf_object_new:nn}
+% \begin{syntax}
+% \cs{pdf_object_new:nn} \Arg{object} \Arg{type}
+% \end{syntax}
+% Declares \meta{object} as a PDF object of \meta{type}, which should be
+% one of
+% \begin{itemize}
+% \item \texttt{array}
+% \item \texttt{dict}
+% \item \texttt{fstream}
+% \item \texttt{stream}
+% \end{itemize}
+% The object may be referenced from this point on, and written later
+% using \cs{pdf_object_write:nn}.
+%
+% Deprecated in favor of \cs{pdf_object_new:n}.
+% \end{function}
+%
+% \begin{function}[added = 2021-02-10]{\pdf_object_write:nn, \pdf_object_write:nx}
+% \begin{syntax}
+% \cs{pdf_object_write:nn} \Arg{object} \Arg{content}
+% \end{syntax}
+% Writes the \meta{content} as content of the \meta{object}. Depending on the
+% \meta{type} declared for the object, the format required for the
+% \meta{data} will vary
+% \begin{itemize}
+% \item[\texttt{array}] A space-separated list of values
+% \item[\texttt{dict}] Key--value pairs in the form
+% \texttt{/\meta{key} \meta{value}}
+% \item[\texttt{fstream}] Two brace groups: \meta{file name} and
+% \meta{file content}
+% \item[\texttt{stream}] Two brace groups: \meta{attributes (dictionary)}
+% and \meta{stream contents}
+% \end{itemize}
+%
+% Deprecated in favor of \cs{pdf_object_write:nnn}.
+% \end{function}
+%
% \begin{implementation}
%
% \section{\pkg{l3pdf} implementation}
@@ -306,27 +340,28 @@
%
% \subsection{Objects}
%
-% \begin{macro}{\pdf_object_new:nn, \pdf_object_write:nn, \pdf_object_write:nx}
-% \begin{macro}[pTF]{\pdf_object_if_exist:n}
+% \begin{macro}{\pdf_object_new:n}
+% \begin{macro}{\pdf_object_write:nnn, \pdf_object_write:nnx}
% \begin{macro}{\pdf_object_ref:n}
% \begin{macro}{\pdf_object_unnamed_write:nn, \pdf_object_unnamed_write:nx}
% \begin{macro}{\pdf_object_ref_last:}
-% Simple to do.
+% \begin{macro}[pTF]{\pdf_object_if_exist:n}
+% Simple to do: all objects create a constant |int| so it is not a
+% backend-specific name.
% \begin{macrocode}
-\cs_new_protected:Npn \pdf_object_new:nn #1#2
- { \@@_backend_object_new:nn {#1} {#2} }
-\prg_new_conditional:Npnn \pdf_object_if_exist:n #1 { p , T , F , TF }
+\cs_new_protected:Npn \pdf_object_new:n #1
{
- \int_if_exist:cTF { c_@@_backend_object_ \tl_to_str:n {#1} _int }
- { \prg_return_true: }
- { \prg_return_false:}
+ \@@_backend_object_new:n {#1}
+ \cs_new_eq:cc
+ { c_@@_backend_object_ \tl_to_str:n {#1} _int }
+ { c_@@_object_ \tl_to_str:n {#1} _int }
}
-\cs_new_protected:Npn \pdf_object_write:nn #1#2
+\cs_new_protected:Npn \pdf_object_write:nnn #1#2#3
{
- \@@_backend_object_write:nn {#1} {#2}
+ \@@_backend_object_write:nnn {#1} {#2} {#3}
\bool_gset_true:N \g_@@_init_bool
}
-\cs_generate_variant:Nn \pdf_object_write:nn { nx }
+\cs_generate_variant:Nn \pdf_object_write:nnn { nnx }
\cs_new:Npn \pdf_object_ref:n #1 { \@@_backend_object_ref:n {#1} }
\cs_new_protected:Npn \pdf_object_unnamed_write:nn #1#2
{
@@ -335,12 +370,19 @@
}
\cs_generate_variant:Nn \pdf_object_unnamed_write:nn { nx }
\cs_new:Npn \pdf_object_ref_last: { \@@_backend_object_last: }
+\prg_new_conditional:Npnn \pdf_object_if_exist:n #1 { p , T , F , TF }
+ {
+ \int_if_exist:cTF { c_@@_object_ \tl_to_str:n {#1} _int }
+ \prg_return_true:
+ \prg_return_false:
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\pdf_pageobject_ref:n}
% \begin{macrocode}
@@ -450,6 +492,34 @@
}
% \end{macrocode}
% \end{macro}
+%
+% \subsection{Deprecated functions}
+%
+% \begin{variable}{\g_@@_object_prop}
+% For tracking objects.
+% \begin{macrocode}
+\prop_new:N \g_@@_object_prop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\pdf_object_new:nn, \pdf_object_write:nn, \pdf_object_write:nx}
+% Wrap up the type data in a prop.
+% \begin{macrocode}
+\cs_new_protected:Npn \pdf_object_new:nn #1#2
+ {
+ \prop_gput:Nnn \g_@@_object_prop {#1} {#2}
+ \@@_backend_object_new:n {#1}
+ }
+\cs_new_protected:Npn \pdf_object_write:nn #1#2
+ {
+ \exp_args:Nnx \@@_backend_object_write:nnn
+ {#1} { \prop_item:Nn \g_@@_object_prop {#1} } {#2}
+ \bool_gset_true:N \g_@@_init_bool
+ }
+\cs_generate_variant:Nn \pdf_object_write:nn { nx }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%</package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
index 542dec79c80..cb0d282a3cf 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
index 11b11e7e18e..6964f9ae473 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
index 9d39718d8ca..9723e115092 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3regex.dtx
index 049b1d46a47..5da0fa163f6 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
index 41202a7949f..218bf5e507a 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
index 1c2b4884e4f..e829802de1c 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sort.dtx
index 88489875ac2..fac7fb0d1f3 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str-convert.dtx
index 7c35f416828..78f6a12649a 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3str.dtx b/Master/texmf-dist/source/latex/l3kernel/l3str.dtx
index b9ad620959c..1ffa124f9ee 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3sys.dtx
index f2fb078a965..2e9b5b939d4 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-case.dtx
index 765a351667e..8a5615a1f63 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
@@ -1435,6 +1435,40 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[EXP]{\@@_change_case_lower_la-x-medieval:nnnN}
+% \begin{macro}[EXP]{\@@_change_case_upper_la-x-medieval:nnnN}
+% Simply swaps of characters.
+% \begin{macrocode}
+\cs_new:cpn { @@_change_case_lower_la-x-medieval:nnnN } #1#2#3#4
+ {
+ \int_compare:nNnTF { `#4 } = { `V }
+ {
+ \@@_change_case_store:e
+ {
+ \char_generate:nn { `u } { \@@_char_catcode:N #4 }
+ }
+ \use:c { @@_change_case_char_next_ #2 :nn }
+ {#2} {#3}
+ }
+ { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 }
+ }
+\cs_new:cpn { @@_change_case_upper_la-x-medieval:nnnN } #1#2#3#4
+ {
+ \int_compare:nNnTF { `#4 } = { `u }
+ {
+ \@@_change_case_store:e
+ {
+ \char_generate:nn { `V } { \@@_char_catcode:N #4 }
+ }
+ \use:c { @@_change_case_char_next_ #2 :nn }
+ {#2} {#3}
+ }
+ { \@@_change_case_char:nnnN {#1} {#2} {#3} #4 }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}[EXP]
% {
% \@@_change_cases_lower_lt:nnnN ,
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx
new file mode 100644
index 00000000000..8d8da0122f9
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3text-map.dtx
@@ -0,0 +1,586 @@
+% \iffalse meta-comment
+%
+%% File: l3text-map.dtx
+%
+% Copyright (C) 2022 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
+%
+% https://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,kernel]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3text-map} package: text processing (mapping)^^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 2022-08-30}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3text-map} implementation}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=text>
+% \end{macrocode}
+%
+% \subsection{Mapping to text}
+%
+% \begin{macro}[EXP]{\text_map_function:nN}
+% \begin{macro}[EXP]{\@@_map_function:nN}
+% \begin{macro}[EXP]{\@@_map_loop:Nnw}
+% \begin{macro}[EXP]{\@@_map_group:Nnn}
+% \begin{macro}[EXP]{\@@_map_space:Nnw}
+% \begin{macro}[EXP]{\@@_map_N_type:NnN}
+% \begin{macro}[EXP]{\@@_map_codepoint:Nnn}
+% \begin{macro}[EXP]{\@@_map_CR:Nnw}
+% \begin{macro}[EXP]{\@@_map_CR:NnN}
+% \begin{macro}[EXP]{\@@_map_class:Nnnn}
+% \begin{macro}[EXP]{\@@_map_class:nNnnn}
+% \begin{macro}[EXP]{\@@_map_class_loop:Nnnnw}
+% \begin{macro}[EXP]{\@@_map_class_end:nw}
+% \begin{macro}[EXP]
+% {
+% \@@_map_Control:Nnn ,
+% \@@_map_Extend:Nnn ,
+% \@@_map_SpacingMark:Nnn ,
+% \@@_map_Prepend:Nnn ,
+% \@@_map_Prepend_aux:Nnn
+% }
+% \begin{macro}[EXP]{\@@_map_Prepend:nNnn}
+% \begin{macro}[EXP]{\@@_map_Prepend_loop:Nnnw}
+% \begin{macro}[EXP]
+% {
+% \@@_map_not_Control:Nnn ,
+% \@@_map_not_Extend:Nnn ,
+% \@@_map_not_SpacingMark:Nnn ,
+% \@@_map_not_Prepend:Nnn ,
+% \@@_map_not_L:Nnn ,
+% \@@_map_not_LV:Nnn ,
+% \@@_map_not_V:Nnn ,
+% \@@_map_not_LVT:Nnn ,
+% \@@_map_not_T:Nnn
+% }
+% \begin{macro}[EXP]
+% {
+% \@@_map_L:Nnn ,
+% \@@_map_LV:Nnn ,
+% \@@_map_V:Nnn ,
+% \@@_map_LVT:Nnn ,
+% \@@_map_T:Nnn
+% }
+% \begin{macro}[EXP]{\@@_map_hangul:Nnnw}
+% \begin{macro}[EXP]{\@@_map_hangul:NnnN}
+% \begin{macro}[EXP]{\@@_map_hangul:Nnnn}
+% \begin{macro}[EXP]{\@@_map_hangul_aux:Nnnnw}
+% \begin{macro}[EXP]{\@@_map_hangul:nNnnnw}
+% \begin{macro}[EXP]{\@@_map_hangul_loop:Nnnnnw}
+% \begin{macro}[EXP]{\@@_map_hangul_next:Nnnn}
+% \begin{macro}[EXP]{\@@_map_hangul_end:nw}
+% \begin{macro}[EXP]
+% {
+% \@@_map_hangul_L:Nnn ,
+% \@@_map_hangul_LV:Nnn ,
+% \@@_map_hangul_V:Nnn ,
+% \@@_map_hangul_LVT:Nnn ,
+% \@@_map_hangul_T:Nnn
+% }
+% \begin{macro}[EXP]
+% {\@@_map_Regional_Indicator:Nnn, \@@_map_Regional_Indicator_aux:Nnn}
+% \begin{macro}[EXP]{\@@_map_lookahead:NnNw}
+% \begin{macro}[EXP]{\@@_map_lookahead:NnNN}
+% \begin{macro}[EXP]{\@@_map_output:Nn}
+% \begin{macro}[EXP]{\text_map_break:}
+% \begin{macro}[EXP]{\text_map_break:n}
+% The standard lead-off for an action loop.
+% \begin{macrocode}
+\cs_new:Npn \text_map_function:nN #1#2
+ { \exp_args:Ne \@@_map_function:nN { \text_expand:n {#1} } #2 }
+\cs_new:Npn \@@_map_function:nN #1#2
+ {
+ \@@_map_loop:Nnw #2 { } #1
+ \q_@@_recursion_tail \q_@@_recursion_stop
+ \prg_break_point:Nn \text_map_break: { }
+ }
+% \end{macrocode}
+% The standard set up for an \enquote{action} loop. Groups are handled by
+% recursion, spaces are treated similarly: both count as grapheme boundaries.
+% For \texttt{N}-type tokens, we filter out control sequences (again
+% a boundary), then move on to further analysis.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_loop:Nnw #1#2#3 \q_@@_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#3}
+ { \@@_map_N_type:NnN }
+ {
+ \tl_if_head_is_group:nTF {#3}
+ { \@@_map_group:Nnn }
+ { \@@_map_space:Nnw }
+ }
+ #1 {#2} #3 \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_group:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ {
+ \@@_map_loop:Nnw #1 { } #2
+ \q_@@_recursion_tail \q_@@_recursion_stop
+ \prg_break_point:Nn \text_map_break: { }
+ }
+ \@@_map_loop:Nnw #1 { }
+ }
+\use:x
+ { \cs_new:Npn \exp_not:N \@@_map_space:Nnw ##1##2 \c_space_tl }
+ {
+ \@@_map_output:Nn #1 {#2}
+ #1 { ~ }
+ \@@_map_loop:Nnw #1 { }
+ }
+\cs_new:Npn \@@_map_N_type:NnN #1#2#3
+ {
+ \@@_if_q_recursion_tail_stop_do:Nn #3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \text_map_break:
+ }
+ \token_if_cs:NTF #3
+ {
+ \@@_map_output:Nn #1 {#2}
+ #1 {#3}
+ \@@_map_loop:Nnw #1 { }
+ }
+ {
+ \@@_codepoint_process:nN
+ { \@@_map_codepoint:Nnn #1 {#2} } #3
+ }
+ }
+% \end{macrocode}
+% We pull out a few special cases here. Carriage returns case needs a bit of
+% context handling so has an auxiliary. Codepoint U+200D is the zero-width
+% joiner, which has no context to concern us: just don't break.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_codepoint:Nnn #1#2#3
+ {
+ \@@_codepoint_compare:nNnTF {#3} = { "0D }
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_CR:Nnw #1 {#3}
+ }
+ {
+ \@@_codepoint_compare:nNnTF {#3} = { "200D }
+ { \@@_map_loop:Nnw #1 {#2#3} }
+ { \@@_map_class:Nnnn #1 {#2} {#3} { Control } }
+ }
+ }
+% \end{macrocode}
+% A carriage return is a boundary unless it is immediately followed by
+% a line feed, in which case that pair is a boundary.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_CR:Nnw #1#2#3 \q_@@_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#3}
+ { \@@_map_CR:NnN #1 {#2} }
+ {
+ #1 {#2}
+ \@@_map_loop:Nnw #1 { }
+ }
+ #3 \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_CR:NnN #1#2#3
+ {
+ \@@_if_q_recursion_tail_stop_do:Nn #3
+ {
+ #1 {#2}
+ \text_map_break:
+ }
+ \bool_lazy_and:nnTF
+ { ! \token_if_cs_p:N #3 }
+ { \int_compare_p:nNn { `#3 } = { "0A } }
+ {
+ \@@_map_output:Nn #1 {#2#3}
+ \@@_map_loop:Nnw #1 { }
+ }
+ { \@@_map_loop:Nnw #1 { } #3 }
+ }
+% \end{macrocode}
+% There are various classes of character, and we deal with them all in
+% the same general way. We need to example the relevant list of codepoints:
+% if we get a hit, then we do whatever the relevant action is. Otherwise
+% we loop, but only if the current codepoint could still match: the
+% loop stops early otherwise and we move forward.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_class:Nnnn #1#2#3#4
+ {
+ \exp_args:Nv \@@_map_class:nNnnn { c_@@_grapheme_ #4 _clist }
+ #1 {#2} {#3} {#4}
+ }
+\cs_new:Npn \@@_map_class:nNnnn #1#2#3#4#5
+ {
+ \@@_map_class_loop:Nnnnw #2 {#3} {#4} {#5}
+ #1 , \q_@@_recursion_tail .. , \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_class_loop:Nnnnw #1#2#3#4 #5 .. #6 ,
+ {
+ \@@_if_q_recursion_tail_stop_do:nn {#5}
+ { \use:c { @@_map_not_ #4 :Nnn } #1 {#2} {#3} }
+ \@@_codepoint_compare:nNnTF {#3} < { "#5 }
+ {
+ \@@_map_class_end:nw
+ { \use:c { @@_map_not_ #4 :Nnn } #1 {#2} {#3} }
+ }
+ {
+ \@@_codepoint_compare:nNnTF {#3} > { "#6 }
+ { \@@_map_class_loop:Nnnnw #1 {#2} {#3} {#4} }
+ {
+ \@@_map_class_end:nw
+ { \use:c { @@_map_ #4 :Nnn } #1 {#2} {#3} }
+ }
+ }
+ }
+\cs_new:Npn \@@_map_class_end:nw #1#2 \q_@@_recursion_stop {#1}
+% \end{macrocode}
+% Break before \emph{and} after.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_Control:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_output:Nn #1 {#3}
+ \@@_map_loop:Nnw #1 { }
+ }
+% \end{macrocode}
+% Keep collecting.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_Extend:Nnn #1#2#3
+ { \@@_map_loop:Nnw #1 {#2#3} }
+\cs_new_eq:NN \@@_map_SpacingMark:Nnn \@@_map_Extend:Nnn
+% \end{macrocode}
+% Outputting anything earlier, the combine with what follows. The only
+% exclusions are control characters.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_Prepend:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_lookahead:NnNw #1 {#3} \@@_map_Prepend_aux:Nnn
+ }
+\cs_new:Npn \@@_map_Prepend_aux:Nnn #1#2#3
+ {
+ \bool_lazy_or:nnTF
+ { \@@_codepoint_compare_p:nNn {#3} = { "0A } }
+ { \@@_codepoint_compare_p:nNn {#3} = { "0D } }
+ {
+ #1 {#2}
+ \@@_map_loop:Nnw #1 {#3}
+ }
+ {
+ \exp_args:NV \@@_map_Prepend:nNnn
+ \c_@@_grapheme_Control_clist
+ #1 {#2} {#3}
+ }
+ }
+\cs_new:Npn \@@_map_Prepend:nNnn #1#2#3#4
+ {
+ \@@_map_Prepend_loop:Nnnw #2 {#3} {#4}
+ #1 , \q_@@_recursion_tail .. , \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_Prepend_loop:Nnnw #1#2#3 #4 .. #5 ,
+ {
+ \@@_if_q_recursion_tail_stop_do:nn {#4}
+ { \@@_map_loop:Nnw #1 {#2#3} }
+ \@@_codepoint_compare:nNnTF {#3} < { "#4 }
+ {
+ \@@_map_class_end:nw
+ { \@@_map_loop:Nnw #1 {#2#3} }
+ }
+ {
+ \@@_codepoint_compare:nNnTF {#3} > { "#5 }
+ { \@@_map_Prepend_loop:Nnnw #1 {#2} {#3} }
+ {
+ \@@_map_class_end:nw
+ { \@@_map_loop:Nnw #1 {#2} #3 }
+ }
+ }
+ }
+% \end{macrocode}
+% Dealing with end-of-class is done such that we can be flexible.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_not_Control:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { Extend } }
+\cs_new:Npn \@@_map_not_Extend:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { SpacingMark } }
+\cs_new:Npn \@@_map_not_SpacingMark:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { Prepend } }
+\cs_new:Npn \@@_map_not_Prepend:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { L } }
+\cs_new:Npn \@@_map_not_L:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { LV } }
+\cs_new:Npn \@@_map_not_LV:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { V } }
+\cs_new:Npn \@@_map_not_V:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { LVT } }
+\cs_new:Npn \@@_map_not_LVT:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { T } }
+\cs_new:Npn \@@_map_not_T:Nnn #1#2#3
+ { \@@_map_class:Nnnn #1 {#2} {#3} { Regional_Indicator } }
+\cs_new:Npn \@@_map_not_Regional_Indicator:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_loop:Nnw #1 {#3}
+ }
+% \end{macrocode}
+% Hangul needs additional treatment. First we have to deal with
+% the start-of-Hangul position: output what we had up to now, then
+% move the the specialist handler. The idea here is to pick off the
+% different codepoint types one at a time, tracking what else can be
+% considered at each stage until we hit the end of the viable types.
+% Other than that, we just keep building up the Hangul codepoints
+% using a dedicated version of the loop from above.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_L:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_hangul:Nnnw
+ #1 {#3} { L ; V ; LV ; LVT }
+ }
+\cs_new:Npn \@@_map_LV:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_hangul:Nnnw
+ #1 {#3} { V ; T }
+ }
+\cs_new_eq:NN \@@_map_V:Nnn \@@_map_LV:Nnn
+\cs_new:Npn \@@_map_LVT:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_hangul:Nnnw
+ #1 {#3} { T }
+ }
+\cs_new_eq:NN \@@_map_T:Nnn \@@_map_LVT:Nnn
+\cs_new:Npn \@@_map_hangul:Nnnw #1#2#3#4 \q_@@_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_map_hangul:NnnN #1 {#2} {#3} }
+ {
+ #1 {#2}
+ \@@_map_loop:Nnw #1 { }
+ }
+ #4 \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_hangul:NnnN #1#2#3#4
+ {
+ \@@_if_q_recursion_tail_stop_do:Nn #4
+ {
+ #1 {#2}
+ \text_map_break:
+ }
+ \token_if_cs:NTF #4
+ {
+ #1 {#2}
+ \@@_map_loop:Nnw #1 { }
+ }
+ {
+ \@@_codepoint_process:nN
+ { \@@_map_hangul:Nnnn #1 {#2} {#3} } #4
+ }
+ }
+\cs_new:Npn \@@_map_hangul:Nnnn #1#2#3#4
+ {
+ \@@_map_hangul_aux:Nnnw #1 {#2} {#4}
+ #3 ; \q_recursion_tail ; \q_recursion_stop
+ }
+\cs_new:Npn \@@_map_hangul_aux:Nnnw #1#2#3#4 ;
+ {
+ \quark_if_recursion_tail_stop_do:nn {#4}
+ { \@@_map_loop:Nnw #1 {#2} #3 }
+ \exp_args:Nv \@@_map_hangul:nNnnnw { c_@@_grapheme_ #4 _clist }
+ #1 {#2} {#3} {#4}
+ }
+\cs_new:Npn \@@_map_hangul:nNnnnw #1#2#3#4#5#6 \q_recursion_stop
+ {
+ \@@_map_hangul_loop:Nnnnnw #2 {#3} {#4} {#5} {#6}
+ #1 , \q_@@_recursion_tail .. , \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_hangul_loop:Nnnnnw #1#2#3#4#5 #6 .. #7 ,
+ {
+ \@@_if_q_recursion_tail_stop_do:nn {#6}
+ { \@@_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
+ \@@_codepoint_compare:nNnTF {#3} < { "#6 }
+ {
+ \@@_map_hangul_end:nw
+ { \@@_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
+ }
+ {
+ \@@_codepoint_compare:nNnTF {#3} > { "#7 }
+ { \@@_map_hangul_loop:Nnnnnw #1 {#2} {#3} {#4} {#5} }
+ {
+ \@@_map_hangul_end:nw
+ { \use:c { @@_map_hangul_ #4 :Nnn } #1 {#2} {#3} }
+ }
+ }
+ }
+\cs_new:Npn \@@_map_hangul_next:Nnnn #1#2#3#4
+ { \@@_map_hangul_aux:Nnnw #1 {#2} {#3} #4 \q_recursion_stop }
+\cs_new:Npn \@@_map_hangul_end:nw #1#2 \q_@@_recursion_stop {#1}
+\cs_new:Npn \@@_map_hangul_L:Nnn #1#2#3
+ {
+ \@@_map_hangul:Nnnw
+ #1 {#2#3} { L V { LV } { LVT } }
+ }
+\cs_new:Npn \@@_map_hangul_LV:Nnn #1#2#3
+ {
+ \@@_map_hangul:Nnnw
+ #1 {#2#3} { VT }
+ }
+\cs_new_eq:NN \@@_map_hangul_V:Nnn \@@_map_hangul_LV:Nnn
+\cs_new:Npn \@@_map_hangul_LVT:Nnn #1#2#3
+ {
+ \@@_map_hangul:Nnnw
+ #1 {#2#3} { T }
+ }
+\cs_new_eq:NN \@@_map_hangul_T:Nnn \@@_map_hangul_LVT:Nnn
+% \end{macrocode}
+% The Regional Indicator rule means looking ahead and dealing with the
+% case where there are two in a row. So we use a look ahead to pick them
+% off. As there is only one range the values are hard-coded.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_Regional_Indicator:Nnn #1#2#3
+ {
+ \@@_map_output:Nn #1 {#2}
+ \@@_map_lookahead:NnNw #1 {#3} \@@_map_Regional_Indicator_aux:Nnn
+ }
+\cs_new:Npn \@@_map_Regional_Indicator_aux:Nnn #1#2#3
+ {
+ \bool_lazy_or:nnTF
+ { \@@_codepoint_compare_p:nNn {#3} < { "1F1E6 } }
+ { \@@_codepoint_compare_p:nNn {#3} > { "1F1FF } }
+ {
+ \@@_map_loop:Nnw #1 {#2} #3
+ }
+ { \@@_map_loop:Nnw #1 {#2#3} }
+ }
+% \end{macrocode}
+% A generic loop-ahead setup.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_lookahead:NnNw #1#2#3#4 \q_@@_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#4}
+ { \@@_map_lookahead:NnNN #1 {#2} #3 }
+ { \@@_map_loop:Nnw #1 {#2} }
+ #4 \q_@@_recursion_stop
+ }
+\cs_new:Npn \@@_map_lookahead:NnNN #1#2#3#4
+ {
+ \@@_if_q_recursion_tail_stop_do:Nn #4 { #1 {#2} }
+ \token_if_cs:NTF #4
+ {
+ #1 {#2}
+ \@@_map_loop:Nnw #1 { }
+ }
+ { \@@_codepoint_process:nN { #3 #1 {#2} } }
+ #4
+ }
+% \end{macrocode}
+% For the end of the process.
+% \begin{macrocode}
+\cs_new:Npn \@@_map_output:Nn #1#2
+ { \tl_if_blank:nF {#2} { #1 {#2} } }
+\cs_new:Npn \text_map_break:
+ { \prg_map_break:Nn \text_map_break: { } }
+\cs_new:Npn \text_map_break:n
+ { \prg_map_break:Nn \text_map_break: }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\text_map_inline:nn}
+% The standard non-expandable inline version.
+% \begin{macrocode}
+\cs_new_protected:Npn \text_map_inline:nn #1#2
+ {
+ \int_gincr:N \g__kernel_prg_map_int
+ \cs_gset_protected:cpn
+ { @@_map_ \int_use:N \g__kernel_prg_map_int :w } ##1 {#2}
+ \exp_args:Nnc \text_map_function:nN {#1}
+ { @@_map_ \int_use:N \g__kernel_prg_map_int :w }
+ \prg_break_point:Nn \text_map_break:
+ { \int_gdecr:N \g__kernel_prg_map_int }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text-purify.dtx
index 966e3518c78..3b5f5cb8c97 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3text.dtx b/Master/texmf-dist/source/latex/l3kernel/l3text.dtx
index df4f2fcde50..3e89563a5e9 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
@@ -184,6 +184,8 @@
% combining dot is removed when uppercasing in these cases. Note that
% \emph{only} the accents used in Lithuanian are covered: the behaviour
% of other accents are not modified.
+% \item Medieval Latin (\texttt{la-xmedieval}).
+% 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
@@ -299,6 +301,62 @@
% \texttt{true}.
% \end{variable}
%
+% \section{Mapping to graphemes}
+%
+% Grapheme splitting is implemented using the algorithm described in Unicode
+% Standard Annex \#29. This includes support for extended grapheme clusters.
+% Text starting with a line feed or carriage return character will drop this
+% due to standard \TeX{} processing. At present extended pictograms are
+% not supported: these may be added in a future release.
+%
+% \begin{function}[rEXP, added = 2022-08-04]{\text_map_function:nN}
+% \begin{syntax}
+% \cs{text_map_function:nN} \meta{text} \Arg{function}
+% \end{syntax}
+% Takes user input \meta{text} and expands as described for
+% \cs{text_expand:n}, then maps over the \emph{graphemes} within the
+% result, passing each grapheme to the \meta{function}.
+% Broadly a grapheme is a \enquote{user perceived character}:
+% the Unicode Consortium describe the decomposition of input to
+% graphemes in depth, and the approach used here implements that
+% algorithm. The \meta{function} should accept one argument as \meta{balanced
+% text}: this may be comprise codepoints or may be a control sequence.
+% With $8$-bit engines, the codepoint(s) themselves may of course be
+% made up of multiple bytes: the mapping will pass the correct codepoints
+% independent of the engine in use.
+% See also \cs{text_map_inline:nn}.
+% \end{function}
+%
+% \begin{function}[added = 2022-08-04]{\text_map_inline:nn}
+% \begin{syntax}
+% \cs{text_map_inline:nn} \meta{text} \Arg{inline function}
+% \end{syntax}
+% Takes user input \meta{text} and expands as described for
+% \cs{text_expand:n}, then maps over the \emph{graphemes} within the
+% result, passing each grapheme to the \meta{inline function}.
+% Broadly a grapheme is a \enquote{user perceived character}:
+% the Unicode Consortium describe the decomposition of input to
+% graphemes in depth, and the approach used here implements that
+% algorithm. The \meta{inline function} should consist of code which
+% receives the grapheme as \meta{balanced
+% text}: this may be comprise codepoints or may be a control sequence.
+% With $8$-bit engines, the codepoint(s) themselves may of course be
+% made up of multiple bytes: the mapping will pass the correct codepoints
+% independent of the engine in use.
+% See also \cs{text_map_function:nN}.
+% \end{function}
+%
+% \begin{function}[rEXP, added = 2022-08-04]
+% {\text_map_break:, \text_map_break:n}
+% \begin{syntax}
+% \cs{text_map_break:}
+% \cs{text_map_break:n} \Arg{code}
+% \end{syntax}
+% Used to terminate a \cs[no-index]{text_map_\ldots} function before all
+% entries in the \meta{text} have been processed. This
+% normally takes place within a conditional statement.
+% \end{function}
+%
% \end{documentation}
%
% \begin{implementation}
@@ -357,11 +415,14 @@
% \end{macro}
%
% \begin{macro}[EXP]{\@@_if_q_recursion_tail_stop_do:Nn}
+% \begin{macro}[EXP]{\@@_if_q_recursion_tail_stop_do:nn}
% Functions to query recursion quarks.
% \begin{macrocode}
\__kernel_quark_new_test:N \@@_if_q_recursion_tail_stop_do:Nn
+\__kernel_quark_new_test:N \@@_if_q_recursion_tail_stop_do:nn
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{variable}{\s_@@_recursion_tail,\s_@@_recursion_stop}
% Internal scan marks quarks.
@@ -581,6 +642,121 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Codepoint utilities}
+%
+% For working with codepoints in an engine-neutral way.
+%
+% \begin{macro}[EXP]{\@@_codepoint_process:nN}
+% \begin{macro}[EXP]{\@@_codepoint_process:nNN}
+% \begin{macro}[EXP]{\@@_codepoint_process:nNNN}
+% \begin{macro}[EXP]{\@@_codepoint_process:nNNNN}
+% Grab a codepoint and apply some code to it: here |#1| should expect one
+% following \emph{balanced text}.
+% \begin{macrocode}
+\bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
+ \cs_new:Npn \@@_codepoint_process:nN #1#2 { #1 {#2} }
+ }
+ {
+ \cs_new:Npn \@@_codepoint_process:nN #1#2
+ {
+ \int_compare:nNnTF { `#2 } > { "80 }
+ {
+ \int_compare:nNnTF { `#2 } < { "E0 }
+ { \@@_codepoint_process:nNN }
+ {
+ \int_compare:nNnTF { `#2 } < { "F0 }
+ { \@@_codepoint_process:nNNN }
+ { \@@_codepoint_process:nNNNN }
+ }
+ }
+ { \use:n }
+ {#1} #2
+ }
+ \cs_new:Npn \@@_codepoint_process:nNN #1#2#3
+ { #1 {#2#3} }
+ \cs_new:Npn \@@_codepoint_process:nNNN #1#2#3#4
+ { #1 {#2#3#4} }
+ \cs_new:Npn \@@_codepoint_process:nNNNN #1#2#3#4#5
+ { #1 {#2#3#4#5} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP, pTF]{\@@_codepoint_compare:nNn}
+% \begin{macro}[EXP]{\@@_codepoint_compare:N, \@@_codepoint_compare_aux:N}
+% \begin{macro}[EXP]{\@@_codepoint_compare:NN}
+% \begin{macro}[EXP]{\@@_codepoint_compare:NNN}
+% \begin{macro}[EXP]{\@@_codepoint_compare:NNNN}
+% Allows comparison for all engines using a first \enquote{character} followed
+% by a codepoint.
+% \begin{macrocode}
+\bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
+ \prg_new_conditional:Npnn
+ \@@_codepoint_compare:nNn #1#2#3 { TF , p }
+ {
+ \int_compare:nNnTF { `#1 } #2 {#3}
+ \prg_return_true: \prg_return_false:
+ }
+ }
+ {
+ \prg_new_conditional:Npnn
+ \@@_codepoint_compare:nNn #1#2#3 { TF , p }
+ {
+ \int_compare:nNnTF { \@@_codepoint_compare:N #1 }
+ #2 {#3}
+ \prg_return_true: \prg_return_false:
+ }
+ \cs_new:Npn \@@_codepoint_compare:N #1
+ {
+ \if_int_compare:w `#1 > "80 \exp_stop_f:
+ \if_int_compare:w `#1 < "E0 \exp_stop_f:
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \@@_codepoint_compare:NN
+ \else:
+ \if_int_compare:w `#1 < "F0 \exp_stop_f:
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_codepoint_compare:NNN
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_codepoint_compare:NNNN
+ \fi:
+ \fi:
+ \else:
+ \exp_after:wN \@@_codepoint_compare_aux:N
+ \fi:
+ #1
+ }
+ \cs_new:Npn \@@_codepoint_compare_aux:N #1 { `#1 }
+ \cs_new:Npn \@@_codepoint_compare:NN #1#2
+ { (`#1 - "C0) * "40 + `#2 - "80 }
+ \cs_new:Npn \@@_codepoint_compare:NNN #1#2#3
+ { (`#1 - "E0) * "1000 + (`#2 - "80) * "40 + `#3 - "80 }
+ \cs_new:Npn \@@_codepoint_compare:NNNN #1#2#3#4
+ {
+ (`#1 - "F0) * "40000
+ + (`#2 - "80) * "1000
+ + (`#3 - "80) * "40
+ + `#4 - "80
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Configuration variables}
%
% \begin{variable}{\l_text_accents_tl, \l_text_letterlike_tl}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl-analysis.dtx
index 728284c8ac7..912436441f3 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
index 647442b82a1..8bdbf5098b7 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
index 5583b55eef0..eb2ef81b195 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
@@ -1795,36 +1795,113 @@
% \end{macro}
%
% \begin{macro}[rEXP]{\char_to_nfd:N}
-% \begin{macro}[rEXP]{\@@_to_nfd:n}
+% \begin{macro}[rEXP]{\@@_to_nfd:n, \@@_to_nfd:e}
% \begin{macro}[rEXP]{\@@_to_nfd:Nw}
-% Look up any \textsc{nfd} and recursively produce the result.
-% \begin{macrocode}
-\cs_new:Npn \char_to_nfd:N #1
+% \begin{macro}[rEXP]{\char_to_nfd:n}
+% \begin{macro}[rEXP]{\char_to_nfd:w}
+% \begin{macro}[rEXP]{\char_nfd_generate:n}
+% \begin{macro}[rEXP]{\char_nfd_generate:nnnn}
+% Look up any \textsc{nfd} and recursively produce the result. Having shared
+% code between Unicode and $8$-bit engines would be ideal, but this would be
+% awkward as we have completely different treatment of catcodes, numbers
+% of tokens, etc. The apparent saving becomes more of a headache than it's
+% worth \dots
+% \begin{macrocode}
+\bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
{
- \cs_if_exist:cTF { c_@@_nfd_ \token_to_str:N #1 _ tl }
+ \cs_new:Npn \char_to_nfd:N #1
{
- \exp_after:wN \exp_after:wN \exp_after:wN \@@_to_nfd:Nw
- \exp_after:wN \exp_after:wN \exp_after:wN #1
- \cs:w c_@@_nfd_ \token_to_str:N #1 _ tl \cs_end:
- \s_@@_stop
+ \cs_if_exist:cTF { c_@@_nfd_ \token_to_str:N #1 _ tl }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_to_nfd:Nw
+ \exp_after:wN \exp_after:wN \exp_after:wN #1
+ \cs:w c_@@_nfd_ \token_to_str:N #1 _tl \cs_end:
+ \s_@@_stop
+ }
+ { \exp_not:n {#1} }
+ }
+ \cs_new_eq:NN \@@_to_nfd:n \char_to_nfd:N
+ \cs_generate_variant:Nn \@@_to_nfd:n { e }
+ \cs_new:Npn \@@_to_nfd:Nw #1#2#3 \s_@@_stop
+ {
+ \@@_to_nfd:e
+ { \char_generate:nn { `#2 } { \@@_change_case_catcode:N #1 } }
+ \tl_if_blank:nF {#3}
+ {
+ \@@_to_nfd:e
+ { \char_generate:nn { `#3 } { \char_value_catcode:n { `#3 } } }
+ }
+ }
+ \cs_new:Npn \char_to_nfd:n #1
+ {
+ \@@_to_nfd:e { \char_generate:nn {#1} { \char_value_catcode:n {#1} } }
}
- { \exp_not:n {#1} }
}
-\cs_set_eq:NN \@@_to_nfd:n \char_to_nfd:N
-\cs_new:Npn \@@_to_nfd:Nw #1#2#3 \s_@@_stop
{
- \exp_args:Ne \@@_to_nfd:n
- { \char_generate:nn { `#2 } { \@@_change_case_catcode:N #1 } }
- \tl_if_blank:nF {#3}
+ \cs_new:Npn \char_to_nfd:N #1 { \exp_not:n {#1} }
+ \cs_new:Npn \char_to_nfd:n #1
+ {
+ \int_compare:nNnTF {#1} > { "80 }
+ { \exp_args:Ne \@@_to_nfd:n { \@@_nfd_generate:n {#1} } }
+ { \@@_nfd_generate:n {#1} }
+ }
+ \cs_new:Npn \@@_to_nfd:n #1
{
- \exp_args:Ne \@@_to_nfd:n
- { \char_generate:nn { `#3 } { \char_value_catcode:n { `#3 } } }
+ \cs_if_exist:cTF { c_@@_nfd_ \tl_to_str:n {#1} _ tl }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_to_nfd:w
+ \cs:w c_@@_nfd_ \tl_to_str:n {#1} _tl \cs_end:
+ \s_@@_stop
+ }
+ { \exp_not:n {#1} }
+ }
+ \cs_new:Npn \@@_to_nfd:w #1#2 \s_@@_stop
+ {
+ \@@_to_nfd:n {#1}
+ \tl_if_blank:nF {#2}
+ { \@@_to_nfd:n {#2} }
}
+ \cs_new:Npn \@@_nfd_generate:n #1
+ {
+ \use:e
+ {
+ \exp_not:N \@@_nfd_generate:nnnn
+ \char_to_utfviii_bytes:n {#1}
+ }
+ }
+ \cs_new:Npn \@@_nfd_generate:nnnn #1#2#3#4
+ {
+ \tl_if_blank:nTF {#2}
+ { \char_generate:nn {#1} { \char_value_catcode:n {#1} } }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#1} { 13 }
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#2} { 13 }
+ \tl_if_blank:nF {#3}
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#3} { 13 }
+ \tl_if_blank:nF {#4}
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#4} { 13 }
+ }
+ }
+ }
+
+ }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \begin{macro}[EXP]
% {
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx b/Master/texmf-dist/source/latex/l3kernel/l3unicode.dtx
index 8ae0f44fe87..737f9704843 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 2022-08-23}
+% \date{Released 2022-08-30}
%
% \maketitle
%
@@ -67,10 +67,9 @@
%<@@=char>
% \end{macrocode}
%
-% Case changing both for strings and \enquote{text} requires data from
-% the Unicode Consortium. Some of this is build in to the format (as
-% \tn{lccode} and \tn{uccode} values) but this covers only the simple
-% one-to-one situations and does not fully handle for example case folding.
+% Text operations requires data from the Unicode Consortium. Data read into
+% Unicode engine formats is at best a small part of what we need, so there
+% is a loader here to set up the appropriate data structures.
%
% As only the data needs to remain at the end of this process, everything
% is set up inside a group. The only thing that is outside is creating a
@@ -78,30 +77,67 @@
% all engines. For performance reasons, some of the code here is very
% low-level: the material is read during loading \pkg{expl3} in package
% mode.
+%
+% Parsing the data files can be the same way for all engines, but the detail
+% of data storage varies depending on whether they are Unicode or $8$-bit
+% internally.Parsing is therefore done by common functions, with the data
+% storage usign engine-specific auxiliaries.
+%
+% Conversion of a codepoint to a character (Unicode engines) or to one
+% or more bytes ($8$-bit engines) is required. We might need those to be
+% detokenized: if not, for Unicode engines they have the current category
+% code.
% \begin{macrocode}
\ior_new:N \g_@@_data_ior
-\bool_lazy_or:nnTF { \sys_if_engine_luatex_p: } { \sys_if_engine_xetex_p: }
- {
- \group_begin:
-% \end{macrocode}
-% Access the primitive but suppress further expansion: active chars are
-% otherwise an issue.
-% \begin{macrocode}
- \cs_set:Npn \@@_generate_char:n #1
- { \tex_detokenize:D \tex_expandafter:D { \tex_Uchar:D " #1 } }
-% \end{macrocode}
-% A fast local implementation for generating characters; the chars may
-% be active, so we prevent further expansion.
-% \begin{macrocode}
- \cs_set:Npx \@@_generate:n #1
+\group_begin:
+ \bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
+ \cs_set:Npn \@@_generate_other:n #1
+ { \tex_detokenize:D \tex_expandafter:D { \tex_Uchar:D #1 } }
+ \cs_set:Npn \@@_generate:n #1
+ {
+ \tex_unexpanded:D \exp_after:wN
+ { \tex_Ucharcat:D #1 ~ \tex_catcode:D #1 ~ }
+ }
+ }
+ {
+ \cs_set:Npn \@@_generate_other:n #1
+ {
+ \tex_detokenize:D \tex_expandafter:D
+ { \tex_expanded:D { \@@_generate:n {#1} } }
+ }
+ \cs_set:Npn \@@_generate:n #1
{
- \exp_not:N \tex_unexpanded:D \exp_not:N \exp_after:wN
+ \use:e
{
- \exp_not:N \tex_Ucharcat:D
- #1 ~
- \tex_catcode:D #1 ~
+ \exp_not:N \@@_generate:nnnn
+ \char_to_utfviii_bytes:n {#1}
}
- }
+ }
+ \cs_set:Npn \@@_generate:nnnn #1#2#3#4
+ {
+ \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#1} { 13 } }
+ \tl_if_blank:nF {#2}
+ {
+ \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#2} { 13 } }
+ \tl_if_blank:nF {#3}
+ {
+ \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#3} { 13 } }
+ \tl_if_blank:nF {#4}
+ {
+ \tex_unexpanded:D
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#4} { 13 } }
+ }
+ }
+ }
+ }
+ }
% \end{macrocode}
% Parse the main Unicode data file for two things. First, we want the titlecase
% exceptions: the one-to-one lower- and uppercase mappings it contains are all
@@ -109,51 +145,52 @@
% just the canonical \textsc{nfd} mappings. Those all yield either one or two
% codepoints, so the split is relatively easy.
% \begin{macrocode}
- \ior_open:Nn \g_@@_data_ior { UnicodeData.txt }
- \cs_set_protected:Npn \@@_data_auxi:w
- #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ;
+ \cs_set_protected:Npn \@@_data_auxi:w
+ #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ;
+ {
+ \tl_if_blank:nF {#6}
{
- \tl_if_blank:nF {#6}
- {
- \tl_if_head_eq_charcode:nNF {#6} < % >
- { \@@_data_auxii:w #1 ; #6 ~ \q_stop }
- }
- \@@_data_auxiii:w #1 ;
+ \tl_if_head_eq_charcode:nNF {#6} < % >
+ { \@@_data_auxii:w #1 ; #6 ~ \q_stop }
}
- \cs_set_protected:Npn \@@_data_auxii:w #1 ; #2 ~ #3 \q_stop
+ \@@_data_auxiii:w #1 ;
+ }
+ \cs_set_protected:Npn \@@_data_auxii:w #1 ; #2 ~ #3 \q_stop
+ {
+ \tl_const:cx
+ { c_@@_nfd_ \@@_generate_other:n { "#1 } _tl }
{
- \tl_const:cx
- { c_@@_nfd_ \@@_generate_char:n {#1} _tl }
- {
- \@@_generate:n { "#2 }
- \tl_if_blank:nF {#3}
- { \@@_generate:n { "#3 } }
+ { \@@_generate:n { "#2 } }
+ {
+ \tl_if_blank:nF {#3}
+ { \@@_generate:n { "#3 } }
}
}
- \cs_set_protected:Npn \@@_data_auxiii:w
- #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ~ \q_stop
- {
- \cs_set_nopar:Npn \l_@@_tmpa_tl {#7}
- \reverse_if:N \if_meaning:w \l_@@_tmpa_tl \c_empty_tl
- \cs_set_nopar:Npn \l_@@_tmpb_tl {#5}
- \reverse_if:N \if_meaning:w \l_@@_tmpa_tl \l_@@_tmpb_tl
- \tl_const:cx
- { c_@@_titlecase_ \@@_generate_char:n {#1} _tl }
- { \@@_generate:n { "#7 } }
- \fi:
- \fi:
- }
- \group_begin:
- \char_set_catcode_space:n { `\ }%
- \ior_map_variable:NNn \g_@@_data_ior \l_@@_tmpa_tl
- {%
- \if_meaning:w \l_@@_tmpa_tl \c_space_tl
- \exp_after:wN \ior_map_break:
- \fi:
- \exp_after:wN \@@_data_auxi:w \l_@@_tmpa_tl \q_stop
- }%
- \group_end:
- \ior_close:N \g_@@_data_ior
+ }
+ \cs_set_protected:Npn \@@_data_auxiii:w
+ #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ~ \q_stop
+ {
+ \cs_set_nopar:Npn \l_@@_tmpa_tl {#7}
+ \reverse_if:N \if_meaning:w \l_@@_tmpa_tl \c_empty_tl
+ \cs_set_nopar:Npn \l_@@_tmpb_tl {#5}
+ \reverse_if:N \if_meaning:w \l_@@_tmpa_tl \l_@@_tmpb_tl
+ \tl_const:cx
+ { c_@@_titlecase_ \@@_generate_other:n { "#1 } _tl }
+ { \@@_generate:n { "#7 } }
+ \fi:
+ \fi:
+ }
+ \ior_open:Nn \g_@@_data_ior { UnicodeData.txt }
+ \group_begin:
+ \char_set_catcode_space:n { `\ }%
+ \ior_map_variable:NNn \g_@@_data_ior \l_@@_tmpa_tl
+ {%
+ \if_meaning:w \l_@@_tmpa_tl \c_space_tl
+ \exp_after:wN \ior_map_break:
+ \fi:
+ \exp_after:wN \@@_data_auxi:w \l_@@_tmpa_tl \q_stop
+ }%
+ \group_end:
% \end{macrocode}
% The other data files all use C-style comments so we have to worry about
% |#| tokens (and reading as strings). The set up for case folding is in two
@@ -162,93 +199,140 @@
% always store the result, splitting up the two or three code points in the input
% as required.
% \begin{macrocode}
- \ior_open:Nn \g_@@_data_ior { CaseFolding.txt }
+ \ior_open:Nn \g_@@_data_ior { CaseFolding.txt }
+ \cs_set_protected:Npn \@@_data_auxi:w #1 ;~ #2 ;~ #3 ; #4 \q_stop
+ {
+ \if:w \tl_head:n { #2 ? } C
+ \reverse_if:N \if_int_compare:w
+ \char_value_lccode:n {"#1} = "#3 ~
+ \tl_const:cx
+ { c_@@_foldcase_ \@@_generate_other:n { "#1 } _tl }
+ { \@@_generate:n { "#3 } }
+ \fi:
+ \else:
+ \if:w \tl_head:n { #2 ? } F
+ \@@_data_auxii:w #1 ~ #3 ~ \q_stop
+ \fi:
+ \fi:
+ }
+ \bool_lazy_or:nnF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
\cs_set_protected:Npn \@@_data_auxi:w #1 ;~ #2 ;~ #3 ; #4 \q_stop
{
- \if:w \tl_head:n { #2 ? } C
- \reverse_if:N \if_int_compare:w
- \char_value_lccode:n {"#1} = "#3 ~
- \tl_const:cx
- { c_@@_foldcase_ \@@_generate_char:n {#1} _tl }
- { \@@_generate:n { "#3 } }
- \fi:
- \else:
- \if:w \tl_head:n { #2 ? } F
- \@@_data_auxii:w #1 ~ #3 ~ \q_stop
- \fi:
+ \if:w \tl_head:n { #2 ? } F
+ \@@_data_auxii:w #1 ~ #3 ~ \q_stop
\fi:
}
- \cs_set_protected:Npn \@@_data_auxii:w #1 ~ #2 ~ #3 ~ #4 \q_stop
+ }
+ \cs_set_protected:Npn \@@_data_auxii:w #1 ~ #2 ~ #3 ~ #4 \q_stop
+ {
+ \tl_const:cx { c_@@_foldcase_ \@@_generate_other:n { "#1 } _tl }
{
- \tl_const:cx { c_@@_foldcase_ \@@_generate_char:n {#1} _tl }
- {
- \@@_generate:n { "#2 }
- \@@_generate:n { "#3 }
- \tl_if_blank:nF {#4}
- { \@@_generate:n { \int_value:w "#4 } }
- }
- }
- \ior_str_map_inline:Nn \g_@@_data_ior
- {
- \reverse_if:N \if:w \c_hash_str \tl_head:w #1 \c_hash_str \q_stop
- \@@_data_auxi:w #1 \q_stop
- \fi:
+ \@@_generate:n { "#2 }
+ \@@_generate:n { "#3 }
+ \tl_if_blank:nF {#4}
+ { \@@_generate:n { \int_value:w "#4 } }
}
- \ior_close:N \g_@@_data_ior
+ }
+ \ior_str_map_inline:Nn \g_@@_data_ior
+ {
+ \reverse_if:N \if:w \c_hash_str \tl_head:w #1 \c_hash_str \q_stop
+ \@@_data_auxi:w #1 \q_stop
+ \fi:
+ }
+ \ior_close:N \g_@@_data_ior
% \end{macrocode}
% For upper- and lowercasing special situations, there is a bit more to
% do as we also have title casing to consider, plus we need to stop part-way
% through the file.
% \begin{macrocode}
- \ior_open:Nn \g_@@_data_ior { SpecialCasing.txt }
- \cs_set_protected:Npn \@@_data_auxi:w
- #1 ;~ #2 ;~ #3 ;~ #4 ; #5 \q_stop
+ \ior_open:Nn \g_@@_data_ior { SpecialCasing.txt }
+ \cs_set_protected:Npn \@@_data_auxi:w
+ #1 ;~ #2 ;~ #3 ;~ #4 ; #5 \q_stop
+ {
+ \use:n { \@@_data_auxii:w #1 ~ lower ~ #2 ~ } ~ \q_stop
+ \use:n { \@@_data_auxii:w #1 ~ upper ~ #4 ~ } ~ \q_stop
+ \str_if_eq:nnF {#3} {#4}
+ { \use:n { \@@_data_auxii:w #1 ~ title ~ #3 ~ } ~ \q_stop }
+ }
+ \cs_set_protected:Npn \@@_data_auxii:w
+ #1 ~ #2 ~ #3 ~ #4 ~ #5 \q_stop
+ {
+ \tl_if_empty:nF {#4}
{
- \use:n { \@@_data_auxii:w #1 ~ lower ~ #2 ~ } ~ \q_stop
- \use:n { \@@_data_auxii:w #1 ~ upper ~ #4 ~ } ~ \q_stop
- \str_if_eq:nnF {#3} {#4}
- { \use:n { \@@_data_auxii:w #1 ~ title ~ #3 ~ } ~ \q_stop }
- }
- \cs_set_protected:Npn \@@_data_auxii:w
- #1 ~ #2 ~ #3 ~ #4 ~ #5 \q_stop
- {
- \tl_if_empty:nF {#4}
+ \tl_const:cx { c_@@_ #2 case_ \@@_generate_other:n { "#1 } _tl }
{
- \tl_const:cx { c_@@_ #2 case_ \@@_generate_char:n {#1} _tl }
- {
- \@@_generate:n { "#3 }
- \@@_generate:n { "#4 }
- \tl_if_blank:nF {#5}
- { \@@_generate:n { "#5 } }
- }
+ \@@_generate:n { "#3 }
+ \@@_generate:n { "#4 }
+ \tl_if_blank:nF {#5}
+ { \@@_generate:n { "#5 } }
}
}
- \ior_str_map_inline:Nn \g_@@_data_ior
+ }
+ \ior_str_map_inline:Nn \g_@@_data_ior
+ {
+ \str_if_eq:eeTF { \tl_head:w #1 \c_hash_str \q_stop } { \c_hash_str }
{
- \str_if_eq:eeTF
- { \tl_head:w #1 \c_hash_str \q_stop }
- { \c_hash_str }
+ \str_if_eq:eeT
+ {#1}
+ { \c_hash_str \c_space_tl Conditional~Mappings }
+ { \ior_map_break: }
+ }
+ { \@@_data_auxi:w #1 \q_stop }
+ }
+ \ior_close:N \g_@@_data_ior
+\group_end:
+
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=text>
+% \end{macrocode}
+%
+% Read the Unicode grapheme data. This is quite easy to handle and we only need
+% codepoints, not characters, so there is no need to worry about the engine in use.
+% As reading as a string is most convenient, we have to do some work to remove
+% spaces: the hardest part of the entire process!
+% \begin{macrocode}
+\ior_new:N \g_@@_data_ior
+\group_begin:
+ \ior_open:Nn \g_@@_data_ior { GraphemeBreakProperty.txt }
+ \cs_set_nopar:Npn \l_@@_tmpa_str { }
+ \cs_set_nopar:Npn \l_@@_tmpb_str { }
+ \cs_set_protected:Npn \@@_data_auxi:w #1 ;~ #2 ~ #3 \q_stop
+ {
+ \str_if_eq:VnF \l_@@_tmpb_str {#2}
+ {
+ \str_if_empty:NF \l_@@_tmpb_str
{
- \str_if_eq:eeT
- {#1}
- { \c_hash_str \c_space_tl Conditional~Mappings }
- { \ior_map_break: }
+ \clist_const:cx { c_@@_grapheme_ \l_@@_tmpb_str _clist }
+ { \exp_after:wN \use_none:n \l_@@_tmpa_str }
+ \cs_set_nopar:Npn \l_@@_tmpa_str { }
}
+ \cs_set_nopar:Npn \l_@@_tmpb_str {#2}
+ }
+ \@@_data_auxii:w #1 .. #1 .. #1 \q_stop
+ }
+ \cs_set_protected:Npn \@@_data_auxii:w #1 .. #2 .. #3 \q_stop
+ {
+ \cs_set_nopar:Npx \l_@@_tmpa_str
+ {
+ \l_@@_tmpa_str ,
+ \tl_trim_spaces:n {#1} .. \tl_trim_spaces:n {#2}
+ }
+ }
+ \ior_str_map_inline:Nn \g_@@_data_ior
+ {
+ \str_if_eq:eeF { \tl_head:w #1 \c_hash_str \q_stop } { \c_hash_str }
+ {
+ \tl_if_blank:nF {#1}
{ \@@_data_auxi:w #1 \q_stop }
}
- \ior_close:N \g_@@_data_ior
- \group_end:
- }
-% \end{macrocode}
-% For the $8$-bit engines, open the stream and close again: this keeps
-% file records the same.
-% \begin{macrocode}
- {
- \group_begin:
- \ior_open:Nn \g_@@_data_ior { UnicodeData.txt }
- \ior_close:N \g_@@_data_ior
- \group_end:
- }
+ }
+ \ior_close:N \g_@@_data_ior
+\group_end:
% \end{macrocode}
%
% \begin{macrocode}
diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex b/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
index e23ee371e13..b5ee93defe0 100644
--- a/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
+++ b/Master/texmf-dist/tex/latex/l3kernel/expl3-code.tex
@@ -52,6 +52,7 @@
%% l3unicode.dtx (with options: `package')
%% l3text.dtx (with options: `package')
%% l3text-case.dtx (with options: `package')
+%% l3text-map.dtx (with options: `package')
%% l3text-purify.dtx (with options: `package')
%% l3candidates.dtx (with options: `package')
%% l3legacy.dtx (with options: `package')
@@ -70,7 +71,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2022-08-23}%
+\def\ExplFileDate{2022-08-30}%
\begingroup
\def\next{\endgroup}%
\expandafter\ifx\csname PackageError\endcsname\relax
@@ -8892,27 +8893,92 @@ Type H <return> for immediate help}\def~{\errmessage{%
}
\cs_generate_variant:Nn \__char_to_utfviii_bytes_output:nnn { f }
\cs_new:Npn \__char_to_utfviii_bytes_end: { }
-\cs_new:Npn \char_to_nfd:N #1
+\bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
{
- \cs_if_exist:cTF { c__char_nfd_ \token_to_str:N #1 _ tl }
+ \cs_new:Npn \char_to_nfd:N #1
{
- \exp_after:wN \exp_after:wN \exp_after:wN \__char_to_nfd:Nw
- \exp_after:wN \exp_after:wN \exp_after:wN #1
- \cs:w c__char_nfd_ \token_to_str:N #1 _ tl \cs_end:
- \s__char_stop
+ \cs_if_exist:cTF { c__char_nfd_ \token_to_str:N #1 _ tl }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \__char_to_nfd:Nw
+ \exp_after:wN \exp_after:wN \exp_after:wN #1
+ \cs:w c__char_nfd_ \token_to_str:N #1 _tl \cs_end:
+ \s__char_stop
+ }
+ { \exp_not:n {#1} }
+ }
+ \cs_new_eq:NN \__char_to_nfd:n \char_to_nfd:N
+ \cs_generate_variant:Nn \__char_to_nfd:n { e }
+ \cs_new:Npn \__char_to_nfd:Nw #1#2#3 \s__char_stop
+ {
+ \__char_to_nfd:e
+ { \char_generate:nn { `#2 } { \__char_change_case_catcode:N #1 } }
+ \tl_if_blank:nF {#3}
+ {
+ \__char_to_nfd:e
+ { \char_generate:nn { `#3 } { \char_value_catcode:n { `#3 } } }
+ }
+ }
+ \cs_new:Npn \char_to_nfd:n #1
+ {
+ \__char_to_nfd:e { \char_generate:nn {#1} { \char_value_catcode:n {#1} } }
}
- { \exp_not:n {#1} }
}
-\cs_set_eq:NN \__char_to_nfd:n \char_to_nfd:N
-\cs_new:Npn \__char_to_nfd:Nw #1#2#3 \s__char_stop
{
- \exp_args:Ne \__char_to_nfd:n
- { \char_generate:nn { `#2 } { \__char_change_case_catcode:N #1 } }
- \tl_if_blank:nF {#3}
+ \cs_new:Npn \char_to_nfd:N #1 { \exp_not:n {#1} }
+ \cs_new:Npn \char_to_nfd:n #1
+ {
+ \int_compare:nNnTF {#1} > { "80 }
+ { \exp_args:Ne \__char_to_nfd:n { \__char_nfd_generate:n {#1} } }
+ { \__char_nfd_generate:n {#1} }
+ }
+ \cs_new:Npn \__char_to_nfd:n #1
+ {
+ \cs_if_exist:cTF { c__char_nfd_ \tl_to_str:n {#1} _ tl }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \__char_to_nfd:w
+ \cs:w c__char_nfd_ \tl_to_str:n {#1} _tl \cs_end:
+ \s__char_stop
+ }
+ { \exp_not:n {#1} }
+ }
+ \cs_new:Npn \__char_to_nfd:w #1#2 \s__char_stop
{
- \exp_args:Ne \__char_to_nfd:n
- { \char_generate:nn { `#3 } { \char_value_catcode:n { `#3 } } }
+ \__char_to_nfd:n {#1}
+ \tl_if_blank:nF {#2}
+ { \__char_to_nfd:n {#2} }
}
+ \cs_new:Npn \__char_nfd_generate:n #1
+ {
+ \use:e
+ {
+ \exp_not:N \__char_nfd_generate:nnnn
+ \char_to_utfviii_bytes:n {#1}
+ }
+ }
+ \cs_new:Npn \__char_nfd_generate:nnnn #1#2#3#4
+ {
+ \tl_if_blank:nTF {#2}
+ { \char_generate:nn {#1} { \char_value_catcode:n {#1} } }
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#1} { 13 }
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#2} { 13 }
+ \tl_if_blank:nF {#3}
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#3} { 13 }
+ \tl_if_blank:nF {#4}
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_not:N \char_generate:nn {#4} { 13 }
+ }
+ }
+ }
+
+ }
}
\cs_new:Npn \char_lowercase:N #1
{ \__char_change_case:nNN { lower } \char_value_lccode:n #1 }
@@ -30233,20 +30299,19 @@ Type H <return> for immediate help}\def~{\errmessage{%
\__pdf_backend_compress_objects:n { \c_false_bool }
}
}
-\cs_new_protected:Npn \pdf_object_new:nn #1#2
- { \__pdf_backend_object_new:nn {#1} {#2} }
-\prg_new_conditional:Npnn \pdf_object_if_exist:n #1 { p , T , F , TF }
+\cs_new_protected:Npn \pdf_object_new:n #1
{
- \int_if_exist:cTF { c__pdf_backend_object_ \tl_to_str:n {#1} _int }
- { \prg_return_true: }
- { \prg_return_false:}
+ \__pdf_backend_object_new:n {#1}
+ \cs_new_eq:cc
+ { c__pdf_backend_object_ \tl_to_str:n {#1} _int }
+ { c__pdf_object_ \tl_to_str:n {#1} _int }
}
-\cs_new_protected:Npn \pdf_object_write:nn #1#2
+\cs_new_protected:Npn \pdf_object_write:nnn #1#2#3
{
- \__pdf_backend_object_write:nn {#1} {#2}
+ \__pdf_backend_object_write:nnn {#1} {#2} {#3}
\bool_gset_true:N \g__pdf_init_bool
}
-\cs_generate_variant:Nn \pdf_object_write:nn { nx }
+\cs_generate_variant:Nn \pdf_object_write:nnn { nnx }
\cs_new:Npn \pdf_object_ref:n #1 { \__pdf_backend_object_ref:n {#1} }
\cs_new_protected:Npn \pdf_object_unnamed_write:nn #1#2
{
@@ -30255,6 +30320,12 @@ Type H <return> for immediate help}\def~{\errmessage{%
}
\cs_generate_variant:Nn \pdf_object_unnamed_write:nn { nx }
\cs_new:Npn \pdf_object_ref_last: { \__pdf_backend_object_last: }
+\prg_new_conditional:Npnn \pdf_object_if_exist:n #1 { p , T , F , TF }
+ {
+ \int_if_exist:cTF { c__pdf_object_ \tl_to_str:n {#1} _int }
+ \prg_return_true:
+ \prg_return_false:
+ }
\cs_new:Npn \pdf_pageobject_ref:n #1
{ \__pdf_backend_pageobject_ref:n {#1} }
\prg_new_conditional:Npnn \pdf_version_compare:Nn #1#2 { p , T , F , TF }
@@ -30317,6 +30388,19 @@ Type H <return> for immediate help}\def~{\errmessage{%
\hbox_to_zero:n
{ \__pdf_backend_destination:nnnn {#1} {#2} {#3} {#4} }
}
+\prop_new:N \g__pdf_object_prop
+\cs_new_protected:Npn \pdf_object_new:nn #1#2
+ {
+ \prop_gput:Nnn \g__pdf_object_prop {#1} {#2}
+ \__pdf_backend_object_new:n {#1}
+ }
+\cs_new_protected:Npn \pdf_object_write:nn #1#2
+ {
+ \exp_args:Nnx \__pdf_backend_object_write:nnn
+ {#1} { \prop_item:Nn \g__pdf_object_prop {#1} } {#2}
+ \bool_gset_true:N \g__pdf_init_bool
+ }
+\cs_generate_variant:Nn \pdf_object_write:nn { nx }
%% File: l3coffins.dtx
\box_new:N \l__coffin_internal_box
\dim_new:N \l__coffin_internal_dim
@@ -31644,143 +31728,219 @@ Type H <return> for immediate help}\def~{\errmessage{%
\prop_gput:Nnn \g_msg_module_type_prop { luatex } { }
%% File: l3unicode.dtx
\ior_new:N \g__char_data_ior
-\bool_lazy_or:nnTF { \sys_if_engine_luatex_p: } { \sys_if_engine_xetex_p: }
- {
- \group_begin:
- \cs_set:Npn \__char_generate_char:n #1
- { \tex_detokenize:D \tex_expandafter:D { \tex_Uchar:D " #1 } }
- \cs_set:Npx \__char_generate:n #1
+\group_begin:
+ \bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
+ \cs_set:Npn \__char_generate_other:n #1
+ { \tex_detokenize:D \tex_expandafter:D { \tex_Uchar:D #1 } }
+ \cs_set:Npn \__char_generate:n #1
{
- \exp_not:N \tex_unexpanded:D \exp_not:N \exp_after:wN
- {
- \exp_not:N \tex_Ucharcat:D
- #1 ~
- \tex_catcode:D #1 ~
- }
+ \tex_unexpanded:D \exp_after:wN
+ { \tex_Ucharcat:D #1 ~ \tex_catcode:D #1 ~ }
+ }
+ }
+ {
+ \cs_set:Npn \__char_generate_other:n #1
+ {
+ \tex_detokenize:D \tex_expandafter:D
+ { \tex_expanded:D { \__char_generate:n {#1} } }
}
- \ior_open:Nn \g__char_data_ior { UnicodeData.txt }
- \cs_set_protected:Npn \__char_data_auxi:w
- #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ;
+ \cs_set:Npn \__char_generate:n #1
{
- \tl_if_blank:nF {#6}
+ \use:e
{
- \tl_if_head_eq_charcode:nNF {#6} < % >
- { \__char_data_auxii:w #1 ; #6 ~ \q_stop }
+ \exp_not:N \__char_generate:nnnn
+ \char_to_utfviii_bytes:n {#1}
}
- \__char_data_auxiii:w #1 ;
}
- \cs_set_protected:Npn \__char_data_auxii:w #1 ; #2 ~ #3 \q_stop
+ \cs_set:Npn \__char_generate:nnnn #1#2#3#4
{
- \tl_const:cx
- { c__char_nfd_ \__char_generate_char:n {#1} _tl }
+ \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#1} { 13 } }
+ \tl_if_blank:nF {#2}
{
- \__char_generate:n { "#2 }
+ \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#2} { 13 } }
\tl_if_blank:nF {#3}
- { \__char_generate:n { "#3 } }
+ {
+ \tex_unexpanded:D \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#3} { 13 } }
+ \tl_if_blank:nF {#4}
+ {
+ \tex_unexpanded:D
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ { \char_generate:nn {#4} { 13 } }
+ }
+ }
}
}
- \cs_set_protected:Npn \__char_data_auxiii:w
- #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ~ \q_stop
+ }
+ \cs_set_protected:Npn \__char_data_auxi:w
+ #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ; #8 ; #9 ;
+ {
+ \tl_if_blank:nF {#6}
{
- \cs_set_nopar:Npn \l__char_tmpa_tl {#7}
- \reverse_if:N \if_meaning:w \l__char_tmpa_tl \c_empty_tl
- \cs_set_nopar:Npn \l__char_tmpb_tl {#5}
- \reverse_if:N \if_meaning:w \l__char_tmpa_tl \l__char_tmpb_tl
- \tl_const:cx
- { c__char_titlecase_ \__char_generate_char:n {#1} _tl }
- { \__char_generate:n { "#7 } }
- \fi:
- \fi:
+ \tl_if_head_eq_charcode:nNF {#6} < % >
+ { \__char_data_auxii:w #1 ; #6 ~ \q_stop }
}
- \group_begin:
- \char_set_catcode_space:n { `\ }%
- \ior_map_variable:NNn \g__char_data_ior \l__char_tmpa_tl
- {%
- \if_meaning:w \l__char_tmpa_tl \c_space_tl
- \exp_after:wN \ior_map_break:
- \fi:
- \exp_after:wN \__char_data_auxi:w \l__char_tmpa_tl \q_stop
- }%
- \group_end:
- \ior_close:N \g__char_data_ior
- \ior_open:Nn \g__char_data_ior { CaseFolding.txt }
+ \__char_data_auxiii:w #1 ;
+ }
+ \cs_set_protected:Npn \__char_data_auxii:w #1 ; #2 ~ #3 \q_stop
+ {
+ \tl_const:cx
+ { c__char_nfd_ \__char_generate_other:n { "#1 } _tl }
+ {
+ { \__char_generate:n { "#2 } }
+ {
+ \tl_if_blank:nF {#3}
+ { \__char_generate:n { "#3 } }
+ }
+ }
+ }
+ \cs_set_protected:Npn \__char_data_auxiii:w
+ #1 ; #2 ; #3 ; #4 ; #5 ; #6 ; #7 ~ \q_stop
+ {
+ \cs_set_nopar:Npn \l__char_tmpa_tl {#7}
+ \reverse_if:N \if_meaning:w \l__char_tmpa_tl \c_empty_tl
+ \cs_set_nopar:Npn \l__char_tmpb_tl {#5}
+ \reverse_if:N \if_meaning:w \l__char_tmpa_tl \l__char_tmpb_tl
+ \tl_const:cx
+ { c__char_titlecase_ \__char_generate_other:n { "#1 } _tl }
+ { \__char_generate:n { "#7 } }
+ \fi:
+ \fi:
+ }
+ \ior_open:Nn \g__char_data_ior { UnicodeData.txt }
+ \group_begin:
+ \char_set_catcode_space:n { `\ }%
+ \ior_map_variable:NNn \g__char_data_ior \l__char_tmpa_tl
+ {%
+ \if_meaning:w \l__char_tmpa_tl \c_space_tl
+ \exp_after:wN \ior_map_break:
+ \fi:
+ \exp_after:wN \__char_data_auxi:w \l__char_tmpa_tl \q_stop
+ }%
+ \group_end:
+ \ior_open:Nn \g__char_data_ior { CaseFolding.txt }
+ \cs_set_protected:Npn \__char_data_auxi:w #1 ;~ #2 ;~ #3 ; #4 \q_stop
+ {
+ \if:w \tl_head:n { #2 ? } C
+ \reverse_if:N \if_int_compare:w
+ \char_value_lccode:n {"#1} = "#3 ~
+ \tl_const:cx
+ { c__char_foldcase_ \__char_generate_other:n { "#1 } _tl }
+ { \__char_generate:n { "#3 } }
+ \fi:
+ \else:
+ \if:w \tl_head:n { #2 ? } F
+ \__char_data_auxii:w #1 ~ #3 ~ \q_stop
+ \fi:
+ \fi:
+ }
+ \bool_lazy_or:nnF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
\cs_set_protected:Npn \__char_data_auxi:w #1 ;~ #2 ;~ #3 ; #4 \q_stop
{
- \if:w \tl_head:n { #2 ? } C
- \reverse_if:N \if_int_compare:w
- \char_value_lccode:n {"#1} = "#3 ~
- \tl_const:cx
- { c__char_foldcase_ \__char_generate_char:n {#1} _tl }
- { \__char_generate:n { "#3 } }
- \fi:
- \else:
- \if:w \tl_head:n { #2 ? } F
- \__char_data_auxii:w #1 ~ #3 ~ \q_stop
- \fi:
+ \if:w \tl_head:n { #2 ? } F
+ \__char_data_auxii:w #1 ~ #3 ~ \q_stop
\fi:
}
- \cs_set_protected:Npn \__char_data_auxii:w #1 ~ #2 ~ #3 ~ #4 \q_stop
+ }
+ \cs_set_protected:Npn \__char_data_auxii:w #1 ~ #2 ~ #3 ~ #4 \q_stop
+ {
+ \tl_const:cx { c__char_foldcase_ \__char_generate_other:n { "#1 } _tl }
+ {
+ \__char_generate:n { "#2 }
+ \__char_generate:n { "#3 }
+ \tl_if_blank:nF {#4}
+ { \__char_generate:n { \int_value:w "#4 } }
+ }
+ }
+ \ior_str_map_inline:Nn \g__char_data_ior
+ {
+ \reverse_if:N \if:w \c_hash_str \tl_head:w #1 \c_hash_str \q_stop
+ \__char_data_auxi:w #1 \q_stop
+ \fi:
+ }
+ \ior_close:N \g__char_data_ior
+ \ior_open:Nn \g__char_data_ior { SpecialCasing.txt }
+ \cs_set_protected:Npn \__char_data_auxi:w
+ #1 ;~ #2 ;~ #3 ;~ #4 ; #5 \q_stop
+ {
+ \use:n { \__char_data_auxii:w #1 ~ lower ~ #2 ~ } ~ \q_stop
+ \use:n { \__char_data_auxii:w #1 ~ upper ~ #4 ~ } ~ \q_stop
+ \str_if_eq:nnF {#3} {#4}
+ { \use:n { \__char_data_auxii:w #1 ~ title ~ #3 ~ } ~ \q_stop }
+ }
+ \cs_set_protected:Npn \__char_data_auxii:w
+ #1 ~ #2 ~ #3 ~ #4 ~ #5 \q_stop
+ {
+ \tl_if_empty:nF {#4}
{
- \tl_const:cx { c__char_foldcase_ \__char_generate_char:n {#1} _tl }
+ \tl_const:cx { c__char_ #2 case_ \__char_generate_other:n { "#1 } _tl }
{
- \__char_generate:n { "#2 }
\__char_generate:n { "#3 }
- \tl_if_blank:nF {#4}
- { \__char_generate:n { \int_value:w "#4 } }
+ \__char_generate:n { "#4 }
+ \tl_if_blank:nF {#5}
+ { \__char_generate:n { "#5 } }
}
}
- \ior_str_map_inline:Nn \g__char_data_ior
- {
- \reverse_if:N \if:w \c_hash_str \tl_head:w #1 \c_hash_str \q_stop
- \__char_data_auxi:w #1 \q_stop
- \fi:
- }
- \ior_close:N \g__char_data_ior
- \ior_open:Nn \g__char_data_ior { SpecialCasing.txt }
- \cs_set_protected:Npn \__char_data_auxi:w
- #1 ;~ #2 ;~ #3 ;~ #4 ; #5 \q_stop
+ }
+ \ior_str_map_inline:Nn \g__char_data_ior
+ {
+ \str_if_eq:eeTF { \tl_head:w #1 \c_hash_str \q_stop } { \c_hash_str }
{
- \use:n { \__char_data_auxii:w #1 ~ lower ~ #2 ~ } ~ \q_stop
- \use:n { \__char_data_auxii:w #1 ~ upper ~ #4 ~ } ~ \q_stop
- \str_if_eq:nnF {#3} {#4}
- { \use:n { \__char_data_auxii:w #1 ~ title ~ #3 ~ } ~ \q_stop }
+ \str_if_eq:eeT
+ {#1}
+ { \c_hash_str \c_space_tl Conditional~Mappings }
+ { \ior_map_break: }
}
- \cs_set_protected:Npn \__char_data_auxii:w
- #1 ~ #2 ~ #3 ~ #4 ~ #5 \q_stop
+ { \__char_data_auxi:w #1 \q_stop }
+ }
+ \ior_close:N \g__char_data_ior
+\group_end:
+
+\ior_new:N \g__text_data_ior
+\group_begin:
+ \ior_open:Nn \g__text_data_ior { GraphemeBreakProperty.txt }
+ \cs_set_nopar:Npn \l__text_tmpa_str { }
+ \cs_set_nopar:Npn \l__text_tmpb_str { }
+ \cs_set_protected:Npn \__text_data_auxi:w #1 ;~ #2 ~ #3 \q_stop
+ {
+ \str_if_eq:VnF \l__text_tmpb_str {#2}
{
- \tl_if_empty:nF {#4}
+ \str_if_empty:NF \l__text_tmpb_str
{
- \tl_const:cx { c__char_ #2 case_ \__char_generate_char:n {#1} _tl }
- {
- \__char_generate:n { "#3 }
- \__char_generate:n { "#4 }
- \tl_if_blank:nF {#5}
- { \__char_generate:n { "#5 } }
- }
+ \clist_const:cx { c__text_grapheme_ \l__text_tmpb_str _clist }
+ { \exp_after:wN \use_none:n \l__text_tmpa_str }
+ \cs_set_nopar:Npn \l__text_tmpa_str { }
}
+ \cs_set_nopar:Npn \l__text_tmpb_str {#2}
}
- \ior_str_map_inline:Nn \g__char_data_ior
+ \__text_data_auxii:w #1 .. #1 .. #1 \q_stop
+ }
+ \cs_set_protected:Npn \__text_data_auxii:w #1 .. #2 .. #3 \q_stop
+ {
+ \cs_set_nopar:Npx \l__text_tmpa_str
{
- \str_if_eq:eeTF
- { \tl_head:w #1 \c_hash_str \q_stop }
- { \c_hash_str }
- {
- \str_if_eq:eeT
- {#1}
- { \c_hash_str \c_space_tl Conditional~Mappings }
- { \ior_map_break: }
- }
- { \__char_data_auxi:w #1 \q_stop }
+ \l__text_tmpa_str ,
+ \tl_trim_spaces:n {#1} .. \tl_trim_spaces:n {#2}
}
- \ior_close:N \g__char_data_ior
- \group_end:
- }
- {
- \group_begin:
- \ior_open:Nn \g__char_data_ior { UnicodeData.txt }
- \ior_close:N \g__char_data_ior
- \group_end:
- }
+ }
+ \ior_str_map_inline:Nn \g__text_data_ior
+ {
+ \str_if_eq:eeF { \tl_head:w #1 \c_hash_str \q_stop } { \c_hash_str }
+ {
+ \tl_if_blank:nF {#1}
+ { \__text_data_auxi:w #1 \q_stop }
+ }
+ }
+ \ior_close:N \g__text_data_ior
+\group_end:
%% File: l3text.dtx
\cs_generate_variant:Nn \tl_if_head_eq_meaning_p:nN { o }
\scan_new:N \s__text_stop
@@ -31791,6 +31951,7 @@ Type H <return> for immediate help}\def~{\errmessage{%
\cs_new:Npn \__text_use_i_delimit_by_q_recursion_stop:nw
#1 #2 \q__text_recursion_stop {#1}
\__kernel_quark_new_test:N \__text_if_q_recursion_tail_stop_do:Nn
+\__kernel_quark_new_test:N \__text_if_q_recursion_tail_stop_do:nn
\scan_new:N \s__text_recursion_tail
\scan_new:N \s__text_recursion_stop
\cs_new:Npn \__text_use_i_delimit_by_s_recursion_stop:nw
@@ -31935,6 +32096,89 @@ Type H <return> for immediate help}\def~{\errmessage{%
}
{ \prg_return_false: }
}
+\bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
+ \cs_new:Npn \__text_codepoint_process:nN #1#2 { #1 {#2} }
+ }
+ {
+ \cs_new:Npn \__text_codepoint_process:nN #1#2
+ {
+ \int_compare:nNnTF { `#2 } > { "80 }
+ {
+ \int_compare:nNnTF { `#2 } < { "E0 }
+ { \__text_codepoint_process:nNN }
+ {
+ \int_compare:nNnTF { `#2 } < { "F0 }
+ { \__text_codepoint_process:nNNN }
+ { \__text_codepoint_process:nNNNN }
+ }
+ }
+ { \use:n }
+ {#1} #2
+ }
+ \cs_new:Npn \__text_codepoint_process:nNN #1#2#3
+ { #1 {#2#3} }
+ \cs_new:Npn \__text_codepoint_process:nNNN #1#2#3#4
+ { #1 {#2#3#4} }
+ \cs_new:Npn \__text_codepoint_process:nNNNN #1#2#3#4#5
+ { #1 {#2#3#4#5} }
+ }
+\bool_lazy_or:nnTF
+ { \sys_if_engine_luatex_p: }
+ { \sys_if_engine_xetex_p: }
+ {
+ \prg_new_conditional:Npnn
+ \__text_codepoint_compare:nNn #1#2#3 { TF , p }
+ {
+ \int_compare:nNnTF { `#1 } #2 {#3}
+ \prg_return_true: \prg_return_false:
+ }
+ }
+ {
+ \prg_new_conditional:Npnn
+ \__text_codepoint_compare:nNn #1#2#3 { TF , p }
+ {
+ \int_compare:nNnTF { \__text_codepoint_compare:N #1 }
+ #2 {#3}
+ \prg_return_true: \prg_return_false:
+ }
+ \cs_new:Npn \__text_codepoint_compare:N #1
+ {
+ \if_int_compare:w `#1 > "80 \exp_stop_f:
+ \if_int_compare:w `#1 < "E0 \exp_stop_f:
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \__text_codepoint_compare:NN
+ \else:
+ \if_int_compare:w `#1 < "F0 \exp_stop_f:
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \__text_codepoint_compare:NNN
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \exp_after:wN \__text_codepoint_compare:NNNN
+ \fi:
+ \fi:
+ \else:
+ \exp_after:wN \__text_codepoint_compare_aux:N
+ \fi:
+ #1
+ }
+ \cs_new:Npn \__text_codepoint_compare_aux:N #1 { `#1 }
+ \cs_new:Npn \__text_codepoint_compare:NN #1#2
+ { (`#1 - "C0) * "40 + `#2 - "80 }
+ \cs_new:Npn \__text_codepoint_compare:NNN #1#2#3
+ { (`#1 - "E0) * "1000 + (`#2 - "80) * "40 + `#3 - "80 }
+ \cs_new:Npn \__text_codepoint_compare:NNNN #1#2#3#4
+ {
+ (`#1 - "F0) * "40000
+ + (`#2 - "80) * "1000
+ + (`#3 - "80) * "40
+ + `#4 - "80
+ }
+ }
\tl_new:N \l_text_accents_tl
\tl_set:Nn \l_text_accents_tl
{ \` \' \^ \~ \= \u \. \" \r \H \v \d \c \k \b \t }
@@ -33352,6 +33596,32 @@ Type H <return> for immediate help}\def~{\errmessage{%
\cs_new_eq:cc { __text_change_case_title_hy-x-yiwn:nnnN }
{ __text_change_case_upper_hy-x-yiwn:nnnN }
}
+\cs_new:cpn { __text_change_case_lower_la-x-medieval:nnnN } #1#2#3#4
+ {
+ \int_compare:nNnTF { `#4 } = { `V }
+ {
+ \__text_change_case_store:e
+ {
+ \char_generate:nn { `u } { \__text_char_catcode:N #4 }
+ }
+ \use:c { __text_change_case_char_next_ #2 :nn }
+ {#2} {#3}
+ }
+ { \__text_change_case_char:nnnN {#1} {#2} {#3} #4 }
+ }
+\cs_new:cpn { __text_change_case_upper_la-x-medieval:nnnN } #1#2#3#4
+ {
+ \int_compare:nNnTF { `#4 } = { `u }
+ {
+ \__text_change_case_store:e
+ {
+ \char_generate:nn { `V } { \__text_char_catcode:N #4 }
+ }
+ \use:c { __text_change_case_char_next_ #2 :nn }
+ {#2} {#3}
+ }
+ { \__text_change_case_char:nnnN {#1} {#2} {#3} #4 }
+ }
\bool_lazy_or:nnT
{ \sys_if_engine_luatex_p: }
{ \sys_if_engine_xetex_p: }
@@ -34622,6 +34892,355 @@ Type H <return> for immediate help}\def~{\errmessage{%
}
}
}
+%% File: l3text-map.dtx
+\cs_new:Npn \text_map_function:nN #1#2
+ { \exp_args:Ne \__text_map_function:nN { \text_expand:n {#1} } #2 }
+\cs_new:Npn \__text_map_function:nN #1#2
+ {
+ \__text_map_loop:Nnw #2 { } #1
+ \q__text_recursion_tail \q__text_recursion_stop
+ \prg_break_point:Nn \text_map_break: { }
+ }
+\cs_new:Npn \__text_map_loop:Nnw #1#2#3 \q__text_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#3}
+ { \__text_map_N_type:NnN }
+ {
+ \tl_if_head_is_group:nTF {#3}
+ { \__text_map_group:Nnn }
+ { \__text_map_space:Nnw }
+ }
+ #1 {#2} #3 \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_group:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ {
+ \__text_map_loop:Nnw #1 { } #2
+ \q__text_recursion_tail \q__text_recursion_stop
+ \prg_break_point:Nn \text_map_break: { }
+ }
+ \__text_map_loop:Nnw #1 { }
+ }
+\use:x
+ { \cs_new:Npn \exp_not:N \__text_map_space:Nnw ##1##2 \c_space_tl }
+ {
+ \__text_map_output:Nn #1 {#2}
+ #1 { ~ }
+ \__text_map_loop:Nnw #1 { }
+ }
+\cs_new:Npn \__text_map_N_type:NnN #1#2#3
+ {
+ \__text_if_q_recursion_tail_stop_do:Nn #3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \text_map_break:
+ }
+ \token_if_cs:NTF #3
+ {
+ \__text_map_output:Nn #1 {#2}
+ #1 {#3}
+ \__text_map_loop:Nnw #1 { }
+ }
+ {
+ \__text_codepoint_process:nN
+ { \__text_map_codepoint:Nnn #1 {#2} } #3
+ }
+ }
+\cs_new:Npn \__text_map_codepoint:Nnn #1#2#3
+ {
+ \__text_codepoint_compare:nNnTF {#3} = { "0D }
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_CR:Nnw #1 {#3}
+ }
+ {
+ \__text_codepoint_compare:nNnTF {#3} = { "200D }
+ { \__text_map_loop:Nnw #1 {#2#3} }
+ { \__text_map_class:Nnnn #1 {#2} {#3} { Control } }
+ }
+ }
+\cs_new:Npn \__text_map_CR:Nnw #1#2#3 \q__text_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#3}
+ { \__text_map_CR:NnN #1 {#2} }
+ {
+ #1 {#2}
+ \__text_map_loop:Nnw #1 { }
+ }
+ #3 \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_CR:NnN #1#2#3
+ {
+ \__text_if_q_recursion_tail_stop_do:Nn #3
+ {
+ #1 {#2}
+ \text_map_break:
+ }
+ \bool_lazy_and:nnTF
+ { ! \token_if_cs_p:N #3 }
+ { \int_compare_p:nNn { `#3 } = { "0A } }
+ {
+ \__text_map_output:Nn #1 {#2#3}
+ \__text_map_loop:Nnw #1 { }
+ }
+ { \__text_map_loop:Nnw #1 { } #3 }
+ }
+\cs_new:Npn \__text_map_class:Nnnn #1#2#3#4
+ {
+ \exp_args:Nv \__text_map_class:nNnnn { c__text_grapheme_ #4 _clist }
+ #1 {#2} {#3} {#4}
+ }
+\cs_new:Npn \__text_map_class:nNnnn #1#2#3#4#5
+ {
+ \__text_map_class_loop:Nnnnw #2 {#3} {#4} {#5}
+ #1 , \q__text_recursion_tail .. , \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_class_loop:Nnnnw #1#2#3#4 #5 .. #6 ,
+ {
+ \__text_if_q_recursion_tail_stop_do:nn {#5}
+ { \use:c { __text_map_not_ #4 :Nnn } #1 {#2} {#3} }
+ \__text_codepoint_compare:nNnTF {#3} < { "#5 }
+ {
+ \__text_map_class_end:nw
+ { \use:c { __text_map_not_ #4 :Nnn } #1 {#2} {#3} }
+ }
+ {
+ \__text_codepoint_compare:nNnTF {#3} > { "#6 }
+ { \__text_map_class_loop:Nnnnw #1 {#2} {#3} {#4} }
+ {
+ \__text_map_class_end:nw
+ { \use:c { __text_map_ #4 :Nnn } #1 {#2} {#3} }
+ }
+ }
+ }
+\cs_new:Npn \__text_map_class_end:nw #1#2 \q__text_recursion_stop {#1}
+\cs_new:Npn \__text_map_Control:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_output:Nn #1 {#3}
+ \__text_map_loop:Nnw #1 { }
+ }
+\cs_new:Npn \__text_map_Extend:Nnn #1#2#3
+ { \__text_map_loop:Nnw #1 {#2#3} }
+\cs_new_eq:NN \__text_map_SpacingMark:Nnn \__text_map_Extend:Nnn
+\cs_new:Npn \__text_map_Prepend:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_lookahead:NnNw #1 {#3} \__text_map_Prepend_aux:Nnn
+ }
+\cs_new:Npn \__text_map_Prepend_aux:Nnn #1#2#3
+ {
+ \bool_lazy_or:nnTF
+ { \__text_codepoint_compare_p:nNn {#3} = { "0A } }
+ { \__text_codepoint_compare_p:nNn {#3} = { "0D } }
+ {
+ #1 {#2}
+ \__text_map_loop:Nnw #1 {#3}
+ }
+ {
+ \exp_args:NV \__text_map_Prepend:nNnn
+ \c__text_grapheme_Control_clist
+ #1 {#2} {#3}
+ }
+ }
+\cs_new:Npn \__text_map_Prepend:nNnn #1#2#3#4
+ {
+ \__text_map_Prepend_loop:Nnnw #2 {#3} {#4}
+ #1 , \q__text_recursion_tail .. , \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_Prepend_loop:Nnnw #1#2#3 #4 .. #5 ,
+ {
+ \__text_if_q_recursion_tail_stop_do:nn {#4}
+ { \__text_map_loop:Nnw #1 {#2#3} }
+ \__text_codepoint_compare:nNnTF {#3} < { "#4 }
+ {
+ \__text_map_class_end:nw
+ { \__text_map_loop:Nnw #1 {#2#3} }
+ }
+ {
+ \__text_codepoint_compare:nNnTF {#3} > { "#5 }
+ { \__text_map_Prepend_loop:Nnnw #1 {#2} {#3} }
+ {
+ \__text_map_class_end:nw
+ { \__text_map_loop:Nnw #1 {#2} #3 }
+ }
+ }
+ }
+\cs_new:Npn \__text_map_not_Control:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { Extend } }
+\cs_new:Npn \__text_map_not_Extend:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { SpacingMark } }
+\cs_new:Npn \__text_map_not_SpacingMark:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { Prepend } }
+\cs_new:Npn \__text_map_not_Prepend:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { L } }
+\cs_new:Npn \__text_map_not_L:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { LV } }
+\cs_new:Npn \__text_map_not_LV:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { V } }
+\cs_new:Npn \__text_map_not_V:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { LVT } }
+\cs_new:Npn \__text_map_not_LVT:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { T } }
+\cs_new:Npn \__text_map_not_T:Nnn #1#2#3
+ { \__text_map_class:Nnnn #1 {#2} {#3} { Regional_Indicator } }
+\cs_new:Npn \__text_map_not_Regional_Indicator:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_loop:Nnw #1 {#3}
+ }
+\cs_new:Npn \__text_map_L:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_hangul:Nnnw
+ #1 {#3} { L ; V ; LV ; LVT }
+ }
+\cs_new:Npn \__text_map_LV:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_hangul:Nnnw
+ #1 {#3} { V ; T }
+ }
+\cs_new_eq:NN \__text_map_V:Nnn \__text_map_LV:Nnn
+\cs_new:Npn \__text_map_LVT:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_hangul:Nnnw
+ #1 {#3} { T }
+ }
+\cs_new_eq:NN \__text_map_T:Nnn \__text_map_LVT:Nnn
+\cs_new:Npn \__text_map_hangul:Nnnw #1#2#3#4 \q__text_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#4}
+ { \__text_map_hangul:NnnN #1 {#2} {#3} }
+ {
+ #1 {#2}
+ \__text_map_loop:Nnw #1 { }
+ }
+ #4 \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_hangul:NnnN #1#2#3#4
+ {
+ \__text_if_q_recursion_tail_stop_do:Nn #4
+ {
+ #1 {#2}
+ \text_map_break:
+ }
+ \token_if_cs:NTF #4
+ {
+ #1 {#2}
+ \__text_map_loop:Nnw #1 { }
+ }
+ {
+ \__text_codepoint_process:nN
+ { \__text_map_hangul:Nnnn #1 {#2} {#3} } #4
+ }
+ }
+\cs_new:Npn \__text_map_hangul:Nnnn #1#2#3#4
+ {
+ \__text_map_hangul_aux:Nnnw #1 {#2} {#4}
+ #3 ; \q_recursion_tail ; \q_recursion_stop
+ }
+\cs_new:Npn \__text_map_hangul_aux:Nnnw #1#2#3#4 ;
+ {
+ \quark_if_recursion_tail_stop_do:nn {#4}
+ { \__text_map_loop:Nnw #1 {#2} #3 }
+ \exp_args:Nv \__text_map_hangul:nNnnnw { c__text_grapheme_ #4 _clist }
+ #1 {#2} {#3} {#4}
+ }
+\cs_new:Npn \__text_map_hangul:nNnnnw #1#2#3#4#5#6 \q_recursion_stop
+ {
+ \__text_map_hangul_loop:Nnnnnw #2 {#3} {#4} {#5} {#6}
+ #1 , \q__text_recursion_tail .. , \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_hangul_loop:Nnnnnw #1#2#3#4#5 #6 .. #7 ,
+ {
+ \__text_if_q_recursion_tail_stop_do:nn {#6}
+ { \__text_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
+ \__text_codepoint_compare:nNnTF {#3} < { "#6 }
+ {
+ \__text_map_hangul_end:nw
+ { \__text_map_hangul_next:Nnnn #1 {#2} {#3} {#5} }
+ }
+ {
+ \__text_codepoint_compare:nNnTF {#3} > { "#7 }
+ { \__text_map_hangul_loop:Nnnnnw #1 {#2} {#3} {#4} {#5} }
+ {
+ \__text_map_hangul_end:nw
+ { \use:c { __text_map_hangul_ #4 :Nnn } #1 {#2} {#3} }
+ }
+ }
+ }
+\cs_new:Npn \__text_map_hangul_next:Nnnn #1#2#3#4
+ { \__text_map_hangul_aux:Nnnw #1 {#2} {#3} #4 \q_recursion_stop }
+\cs_new:Npn \__text_map_hangul_end:nw #1#2 \q__text_recursion_stop {#1}
+\cs_new:Npn \__text_map_hangul_L:Nnn #1#2#3
+ {
+ \__text_map_hangul:Nnnw
+ #1 {#2#3} { L V { LV } { LVT } }
+ }
+\cs_new:Npn \__text_map_hangul_LV:Nnn #1#2#3
+ {
+ \__text_map_hangul:Nnnw
+ #1 {#2#3} { VT }
+ }
+\cs_new_eq:NN \__text_map_hangul_V:Nnn \__text_map_hangul_LV:Nnn
+\cs_new:Npn \__text_map_hangul_LVT:Nnn #1#2#3
+ {
+ \__text_map_hangul:Nnnw
+ #1 {#2#3} { T }
+ }
+\cs_new_eq:NN \__text_map_hangul_T:Nnn \__text_map_hangul_LVT:Nnn
+\cs_new:Npn \__text_map_Regional_Indicator:Nnn #1#2#3
+ {
+ \__text_map_output:Nn #1 {#2}
+ \__text_map_lookahead:NnNw #1 {#3} \__text_map_Regional_Indicator_aux:Nnn
+ }
+\cs_new:Npn \__text_map_Regional_Indicator_aux:Nnn #1#2#3
+ {
+ \bool_lazy_or:nnTF
+ { \__text_codepoint_compare_p:nNn {#3} < { "1F1E6 } }
+ { \__text_codepoint_compare_p:nNn {#3} > { "1F1FF } }
+ {
+ \__text_map_loop:Nnw #1 {#2} #3
+ }
+ { \__text_map_loop:Nnw #1 {#2#3} }
+ }
+\cs_new:Npn \__text_map_lookahead:NnNw #1#2#3#4 \q__text_recursion_stop
+ {
+ \tl_if_head_is_N_type:nTF {#4}
+ { \__text_map_lookahead:NnNN #1 {#2} #3 }
+ { \__text_map_loop:Nnw #1 {#2} }
+ #4 \q__text_recursion_stop
+ }
+\cs_new:Npn \__text_map_lookahead:NnNN #1#2#3#4
+ {
+ \__text_if_q_recursion_tail_stop_do:Nn #4 { #1 {#2} }
+ \token_if_cs:NTF #4
+ {
+ #1 {#2}
+ \__text_map_loop:Nnw #1 { }
+ }
+ { \__text_codepoint_process:nN { #3 #1 {#2} } }
+ #4
+ }
+\cs_new:Npn \__text_map_output:Nn #1#2
+ { \tl_if_blank:nF {#2} { #1 {#2} } }
+\cs_new:Npn \text_map_break:
+ { \prg_map_break:Nn \text_map_break: { } }
+\cs_new:Npn \text_map_break:n
+ { \prg_map_break:Nn \text_map_break: }
+\cs_new_protected:Npn \text_map_inline:nn #1#2
+ {
+ \int_gincr:N \g__kernel_prg_map_int
+ \cs_gset_protected:cpn
+ { __text_map_ \int_use:N \g__kernel_prg_map_int :w } ##1 {#2}
+ \exp_args:Nnc \text_map_function:nN {#1}
+ { __text_map_ \int_use:N \g__kernel_prg_map_int :w }
+ \prg_break_point:Nn \text_map_break:
+ { \int_gdecr:N \g__kernel_prg_map_int }
+ }
%% File: l3text-purify.dtx
\__kernel_quark_new_test:N \__text_if_recursion_tail_stop:N
\cs_new:Npn \text_purify:n #1
diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex b/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
index 2bb475c14fc..7e1fdd7a0e3 100644
--- a/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
+++ b/Master/texmf-dist/tex/latex/l3kernel/expl3-generic.tex
@@ -19,7 +19,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2022-08-23}%
+\def\ExplFileDate{2022-08-30}%
\let\ExplLoaderFileDate\ExplFileDate
\begingroup
\catcode`\_=11
diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx b/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
index 9e63d6fa6f1..c01f3175b53 100644
--- a/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
+++ b/Master/texmf-dist/tex/latex/l3kernel/expl3.ltx
@@ -19,7 +19,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2022-08-23}%
+\def\ExplFileDate{2022-08-30}%
\let\ExplLoaderFileDate\ExplFileDate
\begingroup
\catcode`\_=11
diff --git a/Master/texmf-dist/tex/latex/l3kernel/expl3.sty b/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
index 24372534835..d5a77038172 100644
--- a/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
+++ b/Master/texmf-dist/tex/latex/l3kernel/expl3.sty
@@ -19,7 +19,7 @@
%% and all files in that bundle must be distributed together.
%%
%% File: expl3.dtx
-\def\ExplFileDate{2022-08-23}%
+\def\ExplFileDate{2022-08-30}%
\let\ExplLoaderFileDate\ExplFileDate
\ProvidesPackage{expl3}
[%